Contents
6.4 Primitive Operations of AES
Advanced Encryption Standard
Block cipher
The Advanced Encryption Standard (AES) is a renowned symmetric key algorithm that utilizes a same secret key to encrypt and decrypt a message. It overcomes the limitation of the smaller key size of the Data Encryption Standard (DES) by utilizing a bigger and variable-length key that may take 149 trillion years to crack (assuming a machine could try 255 keys per second—National Institute of Standards and Technology [NIST]). Moreover, it also resolves the slow processing speed of Triple DES (3DES) and utilizes lower resources than that. Therefore, it is preferred as the encryption and decryption standard by the U.S. government. This standard is described in Federal Information Processing Standard (FIPS). AES is now being used worldwide for encrypting digital information, including financial, telecommunications, and government data.
AES supports secret keys of length 128, 192, or 256 bits to encrypt and decrypt a data block of 128 bits. Like other block cipher techniques, it is based on permutations and substitutions. Its design supports implementation in both hardware and software. Moreover, it is royalty-free to use, unlike some commercial encryption algorithms.
Because of the limitations of the previous encryption standard (i.e., DES), the NIST was searching for a new symmetric block cipher technique that could be considered a more robust replacement. In the new proposed technique, it was looking for a cipher that could support multiple key sizes (i.e., key lengths), capable of running efficiently in both hardware and software, and also have a good defense mechanism against various attacking techniques. Thus, a process was initiated on January 2, 1997, where it published a Request for Comments (RFC) for the “Development of a Federal Information Processing Standard for Advanced Encryption Standard.” The entire selection process was fully made open to public scrutiny and comments, because full visibility of any process would ensure the best possible analysis of the designs.
In this flow of the process, NIST publicly called for nominees for the new algorithm on September 12, 1997. The first AES conference was held from August 20–23, 1998. At that conference NIST selected 15 candidates for the AES, which were then subjected to preliminary analysis by the world cryptographic community, including the National Security Agency (NSA). All the selected algorithms were presented, analyzed, and tested at the second AES conference, which was held on March 22–23, 1999. On August 9, 1999, NIST selected five algorithms for extensive analysis:
MARS, submitted by a team from IBM
RC6, submitted by RSA Security
Rijndael, submitted by two Belgian cryptographers, Joan Daemen and Vincent Rijmen
Serpent, submitted by Ross Anderson, Eli Biham, and Lars Knudsen
Twofish, submitted by a team of researchers, including Bruce Schneier
Finally, on October 2, 2000, Rijndael, by Joan Daemen and Vincent Rijmen, was chosen as the Advanced Encryption Standard. On February 28, 2001, the algorithm was included in the publication of a draft by FIPS. Then it was open for public review for 90 days. After that, it was finally included in the Federal Register on December 6, 2001.
One of the principal design goals of AES was to keep it simpler to implement in both hardware and software. Therefore, unlike DES, instead of operating on bits, it operates on bytes, which makes it easier to implement and explain. It works by repeating the same defined steps multiple times, which are called rounds. Each round consists of several processing steps, including one that utilizes an encryption/decryption subkey that is generated from the shared key. Since AES is an iterative symmetric block cipher, it shares a single secret key among the two communicating parties involved in encryption and decryption operations. The allowable key lengths in AES are 128, 192, and 256 bits. Every key is expanded so that a separate subkey(w[i, j], where i and j provide the byte range) could be utilized for every round. Number of rounds of AES generally depends on the key length. A relationship between key length, number of columns in a state, and number of rounds is mentioned in Table 6.1. For instance, if the key length (Nk) is 128 bits or 16 bytes or 4 words, the number of columns (Nb) would be 4 and only 10 rounds (Nr) are performed, where Nb = key length/32.
Table 6.1 Relationship between Key Lengths, Number of Columns in a State, and Total Number of Rounds in AES
KEY LENGTH (Nk) (1 WORD = 32 BITS/4 BYTES) |
NUMBER OF COLUMNS IN STATE (Nb) |
ROUNDS (Nr) |
4 |
4 |
10 |
6 |
6 |
12 |
8 |
8 |
14 |
Figure 6.1 A state of 128-bit key AES, where Sr,c denotes a byte of the rth row and the cth column.
AES, as well as most of the encryption algorithms, is reversible, which means that for the steps performed to complete an encryption, similar steps could be followed to complete a decryption, but in reverse order. In the following section, a detailed description of the operations of AES is explained with examples.
Internally, all the AES operations are performed on a two-dimensional array of bytes called the state. A state constitutes four rows and Nb (Table 6.1) number of columns. Hence, for a 128-bit key, a state consists of four rows and four columns, as depicted in Figure 6.1.
AES is based on five primitive operations:
Exclusive disjunction/exclusive OR (XOR): Exclusive disjunction or exclusive or is a logical operation that outputs true whenever both inputs differ from each other (e.g., one is true and the other is false) (Table 6.2). It is symbolized by the prefix operator J and by the infix operators XOR, EOR, EXOR, ⊻, ⊕, ↮, and ≢.
Substitution (SubByte): A byte is substituted by another byte. AES utilizes a lookup table, also known as S-box, to perform substitutions of encryption, and another S-box, also known as inverse S-box, for decryption. Both S-boxes are given in Tables 6.3 and 6.4, respectively. Each individual byte can be represented by two hex digits where the first (from right) digit represents row and the second digit represents column of the S-box lookup table in the case of encryption, and of the inverse S-box in the case of decryption. For instance, let us assume that {42} is a hexadecimal value that represents a byte. Here, 4 refers to row number and 2 refers to column number; the value over that location would substitute this value, i.e., {2C}.
INPUT |
OUTPUT |
|
0 |
0 |
0 |
0 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
1 |
S-BOX VALUES |
||||||||||||||||
SN |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
A |
B |
C |
D |
E |
F |
0 |
63 |
7C |
77 |
7B |
F2 |
6B |
6F |
C5 |
30 |
01 |
67 |
2B |
FE |
D7 |
AB |
76 |
1 |
CA |
82 |
C9 |
7D |
FA |
59 |
47 |
F0 |
AD |
D4 |
A2 |
AF |
9C |
A4 |
72 |
C0 |
2 |
B7 |
FD |
93 |
26 |
36 |
3F |
F7 |
CC |
34 |
A5 |
E5 |
F1 |
71 |
D8 |
31 |
15 |
3 |
04 |
C7 |
23 |
C3 |
18 |
96 |
05 |
9A |
07 |
12 |
80 |
E2 |
EB |
27 |
B2 |
75 |
4 |
09 |
83 |
2C |
1A |
1B |
6E |
5A |
A0 |
52 |
3B |
D6 |
B3 |
29 |
E3 |
2F |
84 |
5 |
53 |
D1 |
00 |
ED |
20 |
FC |
B1 |
5B |
6A |
CB |
BE |
39 |
4A |
4C |
58 |
CF |
6 |
D0 |
EF |
AA |
FB |
43 |
4D |
33 |
85 |
45 |
F9 |
02 |
7F |
50 |
3C |
9F |
A8 |
7 |
51 |
A3 |
40 |
8F |
92 |
9D |
38 |
F5 |
BC |
B6 |
DA |
21 |
10 |
FF |
F3 |
D2 |
8 |
CD |
0C |
13 |
EC |
5F |
97 |
44 |
17 |
C4 |
A7 |
7E |
3D |
64 |
5D |
19 |
73 |
9 |
60 |
81 |
4F |
DC |
22 |
2A |
90 |
88 |
46 |
EE |
B8 |
14 |
DE |
5E |
0B |
DB |
A |
E0 |
32 |
3A |
0A |
49 |
06 |
24 |
5C |
C2 |
D3 |
AC |
62 |
91 |
95 |
E4 |
79 |
B |
E7 |
C8 |
37 |
6D |
8D |
D5 |
4E |
A9 |
6C |
56 |
F4 |
EA |
65 |
7A |
AE |
08 |
C |
BA |
78 |
25 |
2E |
1C |
A6 |
B4 |
C6 |
E8 |
DD |
74 |
1F |
4B |
BD |
8B |
8A |
D |
70 |
3E |
B5 |
66 |
48 |
03 |
F6 |
0E |
61 |
35 |
57 |
B9 |
86 |
C1 |
1D |
9E |
E |
E1 |
F8 |
98 |
11 |
69 |
D9 |
8E |
94 |
9B |
1E |
87 |
E9 |
CE |
55 |
28 |
DF |
F |
8C |
A1 |
89 |
0D |
BF |
E6 |
42 |
68 |
41 |
99 |
2D |
0F |
B0 |
54 |
BB |
16 |
Rotation (ShiftRows): A simple permutation is performed by rearranging of bytes through rotating a row by a fixed number of cells. It provides a diffusion by the cyclic left shift of the last three rows of the state by different offsets. Row 0 of the state is not shifted, row 1 is shifted 1 byte, row 2 is shifted 2 bytes, and row 3 is shifted 3 bytes. This operation is illustrated in Figure 6.2.
Table 6.4 Inverse S-Box Lookup Table
INVERSE S-BOX VALUES |
||||||||||||||||
SN |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
A |
B |
C |
D |
E |
F |
0 |
52 |
09 |
6A |
D5 |
30 |
36 |
A5 |
38 |
BF |
40 |
A3 |
9E |
81 |
F3 |
D7 |
FB |
1 |
7C |
E3 |
39 |
82 |
9B |
2F |
FF |
87 |
34 |
8E |
43 |
44 |
C4 |
DE |
E9 |
CB |
2 |
54 |
7B |
94 |
32 |
A6 |
C2 |
23 |
3D |
EE |
4C |
95 |
0B |
42 |
FA |
C3 |
4E |
3 |
08 |
2E |
A1 |
66 |
28 |
D9 |
24 |
B2 |
76 |
5B |
A2 |
49 |
6D |
8B |
D1 |
25 |
4 |
72 |
F8 |
F6 |
64 |
86 |
68 |
98 |
16 |
D4 |
A4 |
5C |
CC |
5D |
65 |
B6 |
92 |
5 |
6C |
70 |
48 |
50 |
FD |
ED |
B9 |
DA |
5E |
15 |
46 |
57 |
A7 |
8D |
9D |
84 |
6 |
90 |
D8 |
AB |
00 |
8C |
BC |
D3 |
0A |
F7 |
E4 |
58 |
05 |
B8 |
B3 |
45 |
06 |
7 |
D0 |
2C |
1E |
8F |
CA |
3F |
0F |
02 |
C1 |
AF |
BD |
03 |
01 |
13 |
8A |
6B |
8 |
3A |
91 |
11 |
41 |
4F |
67 |
DC |
EA |
97 |
F2 |
CF |
CE |
F0 |
B4 |
E6 |
73 |
9 |
96 |
AC |
74 |
22 |
E7 |
AD |
35 |
85 |
E2 |
F9 |
37 |
E8 |
1C |
75 |
DF |
6E |
A |
47 |
F1 |
1A |
71 |
1D |
29 |
C5 |
89 |
6F |
B7 |
62 |
0E |
AA |
18 |
BE |
1B |
B |
FC |
56 |
3E |
4B |
C6 |
D2 |
79 |
20 |
9A |
DB |
C0 |
FE |
78 |
CD |
5A |
F4 |
C |
1F |
DD |
A8 |
33 |
88 |
07 |
C7 |
31 |
B1 |
12 |
10 |
59 |
27 |
80 |
EC |
5F |
D |
60 |
51 |
7F |
A9 |
19 |
B5 |
4A |
0D |
2D |
E5 |
7A |
9F |
93 |
C9 |
9C |
EF |
E |
A0 |
E0 |
3B |
4D |
AE |
2A |
F5 |
B0 |
C8 |
EB |
BB |
3C |
83 |
53 |
99 |
61 |
F |
17 |
2B |
04 |
7E |
BA |
77 |
D6 |
26 |
E1 |
69 |
14 |
63 |
55 |
21 |
0C |
7D |
Figure 6.2 Shift row operation of AES.
In case of decryption, inverse shift rows (InvShiftRows) are performed, which follows a process similar to that of ShiftRows, only the shifting is done to the right.
MixColumn: It operates on each column individually where a single byte of a column is mapped into a new value that is a function of all four bytes in that column. Each column of the state is replaced by multiplying with a 4 × Nb matrix in the Galois field 28, also denoted as GF(28). The mathematics behind this is beyond the scope of this book. An example matrix is given for 128-bit key in Figure 6.3.
The first result byte is calculated by multiplying four values of the state column against four values of the first row of the matrix. The result of each multiplication is then XORed to produce 1 byte like below:
S0,0 = (S0,0*2) XOR (S1,0*3) XOR (S2,0*1) XOR (S3,0*1)
This procedure is repeated again with each byte of all columns of the state, until there is no more state column. As a result of this multiplication, the four bytes in the first column are replaced by the following:
S0,0 = (S0,0*2) XOR (S1,0*3) XOR (S2,0*1) XOR (S3,0*1)
S1,0 = (S0,0*1) XOR (S1,0*2) XOR (S2,0*3) XOR (S3,0*1)
S2,0 = (S0,0*1) XOR (S1,0*1) XOR (S2,0*2) XOR (S3,0*3)
S3,0 = (S0,0*3) XOR (S1,0*1) XOR (S2,0*1) XOR (S3,0*2)
This multiplication value also could be achieved using a two-table lookup represented in hexadecimal numbers and indexed with a hexadecimal digit. They are called the L-Table and E-Table and are given in Tables 6.5 and 6.6, respectively.
The result of the multiplication could be found from the L lookup table, followed by the addition of the results (+, not a bitwise AND), followed by a lookup to the E-table. The numbers being multiplied are 1 byte each and are represented in two hexadecimal digits. The first digit is used as row index and the last digit as column index of the L-table. Then, two values acquired from the L-table are added, which results in another byte. The resultant byte is used to look up from E-table, following a procedure similar to that of the L-table. For instance, let us assume that the two hex values being multiplied are 87*02. First, we have to look up the L-table to find out the substitution values, i.e., 74 and 19. Then, add the two acquired values together, which is 8D in this example. If the added value is greater than FF, then FF needs to be subtracted from the added value. The final step is to look up the addition result on the E-table. Note that any number multiplied by 1 is equal to itself and does not need to go through the above-mentioned procedure, e.g., 87*1 = 87.
Figure 6.3 128-bit key state and its multiplication matrix.
L-TABLE |
||||||||||||||||
SN |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
A |
B |
C |
D |
E |
F |
0 |
|
00 |
19 |
01 |
32 |
02 |
1A |
C6 |
4B |
C7 |
1B |
68 |
33 |
E |
DF |
03 |
1 |
64 |
04 |
E0 |
0E |
34 |
8D |
81 |
EF |
4C |
71 |
08 |
C8 |
F8 |
69 |
1C |
C1 |
2 |
7D |
C2 |
1D |
B5 |
F9 |
B9 |
27 |
6A |
4D |
E4 |
A6 |
72 |
9A |
C9 |
09 |
78 |
3 |
65 |
2F |
8A |
05 |
21 |
0F |
E1 |
24 |
12 |
F0 |
82 |
45 |
35 |
93 |
DA |
8E |
4 |
96 |
8F |
DB |
BD |
36 |
D0 |
CE |
94 |
13 |
5C |
D2 |
F1 |
40 |
46 |
83 |
38 |
5 |
66 |
DD |
FD |
30 |
BF |
06 |
8B |
62 |
B3 |
25 |
E2 |
98 |
22 |
88 |
91 |
10 |
6 |
7E |
6E |
48 |
C3 |
A3 |
B6 |
1E |
42 |
3A |
6B |
28 |
54 |
FA |
85 |
3D |
BA |
7 |
2B |
79 |
0A |
15 |
9B |
9F |
5E |
CA |
4E |
D4 |
AC |
E5 |
F3 |
73 |
A7 |
57 |
8 |
AF |
58 |
A8 |
50 |
F4 |
EA |
D6 |
74 |
4F |
AE |
E9 |
D5 |
E7 |
E6 |
AD |
E8 |
9 |
2C |
D7 |
75 |
7A |
EB |
16 |
0B |
F5 |
59 |
CB |
5F |
B0 |
9C |
A9 |
51 |
A0 |
A |
7F |
0C |
F6 |
6F |
17 |
C4 |
49 |
EC |
D8 |
43 |
1F |
2D |
A4 |
76 |
7B |
B7 |
B |
CC |
BB |
3E |
5A |
FB |
60 |
B1 |
86 |
3B |
52 |
A1 |
6C |
AA |
55 |
29 |
9D |
C |
97 |
B2 |
87 |
90 |
61 |
BE |
DC |
FC |
BC |
95 |
CF |
CD |
37 |
3F |
5B |
D1 |
D |
53 |
39 |
84 |
3C |
41 |
A2 |
6D |
47 |
14 |
2A |
9E |
5D |
56 |
F2 |
D3 |
AB |
E |
44 |
11 |
92 |
D9 |
23 |
20 |
2E |
89 |
B4 |
7C |
B8 |
26 |
77 |
99 |
E3 |
A5 |
F |
67 |
4A |
ED |
DE |
C5 |
31 |
FE |
18 |
0D |
63 |
8C |
80 |
C0 |
F7 |
70 |
07 |
E-TABLE |
||||||||||||||||
SN |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
A |
B |
C |
D |
E |
F |
0 |
01 |
03 |
05 |
0F |
11 |
33 |
55 |
FF |
1A |
2E |
72 |
96 |
A1 |
F8 |
13 |
35 |
1 |
5F |
E1 |
38 |
48 |
D8 |
73 |
95 |
A4 |
F7 |
02 |
06 |
0A |
1E |
22 |
66 |
AA |
2 |
E5 |
34 |
5C |
E4 |
37 |
59 |
EB |
26 |
6A |
BE |
D9 |
70 |
90 |
AB |
E6 |
31 |
3 |
53 |
F5 |
04 |
0C |
14 |
3C |
44 |
CC |
4F |
D1 |
68 |
B8 |
D3 |
6E |
B2 |
CD |
4 |
4C |
D4 |
67 |
A9 |
E0 |
3B |
4D |
D7 |
62 |
A6 |
F1 |
08 |
18 |
28 |
78 |
88 |
5 |
83 |
9E |
B9 |
D0 |
6B |
BD |
DC |
7F |
81 |
98 |
B3 |
CE |
49 |
DB |
76 |
9A |
6 |
B5 |
C4 |
57 |
F9 |
10 |
30 |
50 |
F0 |
0B |
1D |
27 |
69 |
BB |
D6 |
61 |
A3 |
7 |
FE |
19 |
2B |
7D |
87 |
92 |
AD |
EC |
2F |
71 |
93 |
AE |
E9 |
20 |
60 |
A0 |
8 |
FB |
16 |
3A |
4E |
D2 |
6D |
B7 |
C2 |
5D |
E7 |
32 |
56 |
FA |
15 |
3F |
41 |
9 |
C3 |
5E |
E2 |
3D |
47 |
C9 |
40 |
C0 |
5B |
ED |
2C |
74 |
9C |
BF |
DA |
75 |
A |
9F |
BA |
D5 |
64 |
AC |
EF |
2A |
7E |
82 |
9D |
BC |
DF |
7A |
8E |
89 |
80 |
B |
9B |
B6 |
C1 |
58 |
E8 |
23 |
65 |
AF |
EA |
25 |
6F |
B1 |
C8 |
43 |
C5 |
54 |
C |
FC |
1F |
21 |
63 |
A5 |
F4 |
07 |
09 |
1B |
2D |
77 |
99 |
B0 |
CB |
46 |
CA |
D |
45 |
CF |
4A |
DE |
79 |
8B |
86 |
91 |
A8 |
E3 |
3E |
42 |
C6 |
51 |
F3 |
0E |
E |
12 |
36 |
5A |
EE |
29 |
7B |
8D |
8C |
8F |
8A |
85 |
94 |
A7 |
F2 |
0D |
17 |
F |
39 |
4B |
DD |
7C |
84 |
97 |
A2 |
FD |
1C |
24 |
6C |
B4 |
C7 |
52 |
F6 |
01 |
An example of MixColumn during encryption is given below:
Input = 87 6E 46 A6
S0,0 = (87*2) XOR (6E*3) XOR (46*1) XOR (A6*1)
= E(L(87) + L(02)) XOR E(L(6E) + L(03)) XOR 46 XOR A6
= E(8D) XOR E(3E) XOR 46 XOR A6
= 15 XOR B2 XOR 46 XOR A6
= 47
Similarly, one can calculate the other values of the state. In the case of decryption, the inverse mix column (InvMixColumn) technique is utilized, which follows the same process as MixColumn, but multiplications are performed on a different multiplication matrix. InvMixColumn utilizes the multiplication matrix shown in Table 6.7.
Table 6.7 Inverse Multiplication Matrix
0E |
0B |
0D |
09 |
09 |
0E |
0B |
0D |
0D |
09 |
0E |
0B |
0B |
0D |
09 |
0E |
AddRoundKey: This is a simple operation where each byte of the state is XORed with each byte of the round key, which is a portion of the expanded key. In the next section, a detailed description of the key expansion technique of AES is elaborated. Figure 6.4 illustrates the technique of AddRoundKey transformation.
The basic encryption and decryption structure of AES is illustrated in Figure 6.5. Here, a 128-bit key length is considered. Therefore, both encryption and decryption must go through 10 rounds before producing the desired output. There are 12 rounds for a 192-bit key and 14 rounds for a 256-bit key. It can be observed from the figure that every round generally performs four operations: (1) SubBytes/InvSubBytes, (2) ShiftRows/InvShiftRows, (3) MixColumns/InvMixColumns, and (4) AddRoundKey. One of them is permutation and the other three are substitutions. However, the final round comprises only three operations, excluding MixColumns/InvMixColumns. The expanded key is only utilized by the AddRoundKey operations. Each operation is easily reversible, thus making it easy to implement in both hardware and software. Similar to most of the block ciphers, the decryption algorithm utilizes the key in reverse order.
As mentioned earlier, since AES supports symmetric key, a secret key must be shared between the two parties. AES provides flexibility regarding selecting a key length. A key could be 128, 192, or 256 bits long. Since every round utilizes a new subkey, prior to encryption or decryption, the key must be expanded according to the number of rounds. This process is called key expansion.
Figure 6.5 AES encryption and decryption techniques.
The key expansion routine takes an input key of size Nk and produces a linear array of size, Nb × (Nr + 1), where a number of columns in states is (Nb) and the number of rounds (Nr) depends on key length (Nk).
For instance, Nr is 10 when Nk is 4, which is illustrated in Table 6.1. Let us denote a word in the expanded key as w[i], where i is the ith word of that key. Algorithm 6.1 shows a key expansion algorithm.
Algorithm 6.1: KeyExpansion(key)
Begin
word temp;
for i ← 0 to (Nk - 1)
w[i] ← (unsigned char) key[4*i] << 24) |
((unsigned char) key[4*i+1] << 16) |
((unsigned char) key[4*i+2]<<8) |
((unsigned char) key[4*i+3]);
end for
for i ← (Nk - 1) to Nb × Nr
temp = w[i-1];
if (imodNk = = 0)
temp = SubWord(RotWord(temp))
(Rcon[i/Nk] << 24);
else if(Nk> 6 and(i mod Nk) = = 4)
temp = SubWord(temp);
end if
w[i] = w[i-Nk] ⊕ temp;
end for
End
From Algorithm 6.1, we can easily identify the functions necessary for the expanding key:
RotWord: This function does a circular shift on 4 bytes, similar to the shift row function, e.g., 0, 1, 2, 3 to 1, 2, 3, 0.
SubWord: It does a similar transformation, which is described in the SubByte operation. It utilizes the S-box table to substitute a byte.
XOR with round constant (Rcon): For every round in key expansion, the result acquired from function 1 and function 2 is XORed with a round constant value Rcon[i]. These values are shown in Table 6.8.
Table 6.8 Rounds and Their Respective Constants
Round[j] |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
Rcon[j] |
01 |
02 |
04 |
08 |
10 |
20 |
40 |
80 |
1B |
36 |
Let us assume that the secret key shared between two parties is aes 128 pass key, which is 128 bits long. Therefore, Nk is 4, Nb is 4, and Nr is 10 for this key length. A hexadecimal representation of the key is shown in Figure 6.6.
This key is utilized to expand the key to Nb × (Nr + 1) bytes, which is 44 bytes in this example. A detailed description of the steps is presented in previous sections. In this section, we demonstrate how the round key for the first round, i.e., w[4, 7], can be calculated while w[0, 3] is given. From Figure 6.6, we get
w[0] = 1A91F720 |
w[1] = 5E456706 |
w[2] = A25B66DE |
w[3] = 5F145988 |
W[I] |
W[I – 1] OR TEMP |
AFTER ROTWORD |
AFTER SUBWORD |
RCON[I] |
AFTER XOR WITH RCON[I] |
W[I – 4] |
W[I] = TEMP XOR W[I – 4] |
4 |
5F145988 |
1459885F |
FACBC4CF |
1000000 |
EACBC4CF |
1A91F720 |
E15A33EF |
5 |
E15A33EF |
5A33EFE1 |
BEC3DFF8 |
1000000 |
AEC3DFF8 |
5E456706 |
BF1F54E9 |
6 |
BF1F54E9 |
1F54E9BF |
C0201E08 |
1000000 |
D0201E08 |
A25B66DE |
1D443237 |
7 |
1D443237 |
4432371D |
1B2394A4 |
1000000 |
0B2394A4 |
5F145988 |
42506BBF |
By repeating the similar procedures, the remaining words of the expanded key are generated.
In AES, a plaintext has to travel through Nr number of rounds before producing the cipher. Again, each round comprises four different operations. One operation is permutation and the other three are substitutions. They are (1) SubBytes, (2) ShiftRows, (3) MixColumns, and (4) AddRoundKey. All these operations are detailed previously. Algorithm 6.2 gives a high-level description of the encryption algorithm.
Figure 6.6 Hex value representations of the secret key.
Algorithm 6.2: Encryption (PlainText)
Begin
State = plainText
1. KeyExpansion
2. AddRoundKey (State, ExpandedKey[0])
3. for r ← 1 to (Nr - 1)
a. SubBytes (State, S-box)
b. ShiftRows (State)
c. MixColumns (State)
d. AddRoundKey (State, ExpandedKey[r])
end for
4. SubBytes (State, S-box)
5. ShiftRows (State)
6. AddRoundKey (State, ExpandedKey[Nr])
Out = CipherText
End
Let us assume that the plaintext we are going to encrypt is string 2 encrypt using the key stated in Section 6.7. To encrypt, this string is copied to the state, and hexadecimal representations are given in Figure 6.7.
The steps of various rounds with their corresponding values are portrayed in tabular format in Table 6.9.
The decryption routine takes the encrypted string/state as input or output of the encryption routine and performs a reverse operation.
Figure 6.7 Hex value representations of plaintext.
Table 6.9 Steps of the AES Encryption
ROUND NUMBER |
START OF A ROUND |
AFTER SUBBYTES |
AFTER SHIFTROWS |
AFTER MIXCOLUMNS |
ROUND KEY VALUE |
ROUND OUTPUT |
INP |
736E2072 |
|
|
|
1A5EA25F |
6930822D |
|
74676579 |
|
|
|
91455B14 |
E5223E6D |
|
72206E70 |
|
|
|
F7676659 |
85470829 |
|
69326374 |
|
|
|
2006DE88 |
4934BDFC |
1 |
6930822D |
F90413D8 |
F90413D8 |
C75BED01 |
E1BF1D42 |
26E4F043 |
|
E5223E6D |
D993B23C |
93B23CD9 |
24B4D1F0 |
5A1F4450 |
7EAB95A0 |
|
85470829 |
97A03095 |
30A597A0 |
C1AA32D4 |
3354326B |
F2FE00BF |
|
4934BDFC |
3B187AB0 |
B03B187A |
C86DAEFE |
EFE937BF |
27849941 |
2 |
26E4F043 |
F7698C1A |
F7698C1A |
B368EE6F |
B00F1250 |
0367FC3F |
|
7EAB95A0 |
F3622AE0 |
622AE0F3 |
15E988DF |
253A7E2E |
30D3F6F1 |
|
F2FE00BF |
89BB6308 |
630889BB |
CD1C84AD |
3B6F5D36 |
F673D99B |
|
27849941 |
CC5FEE83 |
83CC5FEE |
1E1A58A1 |
C32A1DA2 |
DD304503 |
3 |
0367FC3F |
7B85B075 |
7B85B075 |
1202C507 |
858A98C8 |
97885DCF |
|
30D3F6F1 |
046642A1 |
6642A104 |
93FC2B99 |
201A644A |
B3E64FD3 |
|
F673D99B |
428F3514 |
3514428F |
FAB799C6 |
016E3305 |
FBD9AAC3 |
|
DD304503 |
C1046E7B |
7BC1046E |
285B20C8 |
90BAA705 |
B8E187CD |
4 |
97885DCF |
88C44C8A |
88C44C8A |
9346C59A |
5BD14981 |
C8978C1B |
|
B3E64FD3 |
6D8E8466 |
8E84666D |
DDC96918 |
4B51357F |
96985C67 |
|
FBD9AAC3 |
0F35AC2E |
AC2E0F35 |
99A827B4 |
6A043732 |
F3AC1086 |
|
B8E187CD |
6CF817BD |
BD6CF817 |
C02556F3 |
78C26560 |
B8E73393 |
5 |
C8978C1B |
E88864AF |
E88864AF |
17FDC5BC |
99480180 |
8EB5C43C |
|
96985C67 |
90464A85 |
464A8590 |
FDBCF6FF |
68390C73 |
9585FA8C |
|
F3AC1086 |
0D91CA44 |
CA440D91 |
5EFE5C58 |
BABE89BB |
E440D5E3 |
|
B8E73393 |
6C94C3DC |
DC6C94C3 |
0C551776 |
74B6D3B3 |
78E3C4C5 |
6 |
8EB5C43C |
19D51CEB |
19D51CEB |
356BECA6 |
367E7FFF |
03159359 |
|
9585FA8C |
2A972D64 |
972D642A |
8F007EB8 |
82BBB7C4 |
0DBBC97C |
|
E440D5E3 |
69090311 |
03116909 |
790599F7 |
D769E05B |
AE6C79AC |
|
78E3C4C5 |
BC111CA6 |
A6BC111C |
E83B0B3D |
B90FDC6F |
5134D752 |
7 |
03159359 |
7B59DCCB |
7B59DCCB |
658E6FB1 |
6A146B94 |
0F9A0425 |
|
0DBBC97C |
D7EADD10 |
EADD10D7 |
7581D380 |
BB00B773 |
CE8164F3 |
|
AE6C79AC |
E450B691 |
B691E450 |
E6D537AE |
7F16F6AD |
99C3C103 |
|
5134D752 |
D1180E00 |
00D1180E |
D11EBBDD |
AFA07C13 |
7EBEC7CE |
8 |
0F9A0425 |
76B8F23F |
76B8F23F |
0B26A810 |
65711A8E |
6E57B29E |
|
CE8164F3 |
8B0C430D |
0C430D8B |
6D406F86 |
2E2E99EA |
436EF66C |
|
99C3C103 |
EE2E787B |
787BEE2E |
0C03D1B9 |
0214E24F |
0E1733F6 |
|
7EBEC7CE |
F3AEC68B |
8BF3AEC6 |
E316A973 |
8D2D5142 |
6E3BF831 |
9 |
6E57B29E |
9F5B370B |
9F5B370B |
9BADD789 |
F988921C |
62254595 |
|
436EF66C |
1A9F4250 |
9F42501A |
23869375 |
AA841DF7 |
89028E82 |
|
0E1733F6 |
ABF0C342 |
C342ABF0 |
CF271729 |
2E3AD897 |
E11DCFBE |
|
6E3BF831 |
9FE241C7 |
C79FE241 |
73C87D75 |
94B9E8AA |
E77195DF |
10 |
62254595 |
AA3F6E2A |
AA3F6E2A |
|
A72FBDA1 |
0D10D38B |
|
89028E82 |
A7771913 |
771913A7 |
|
22A6BB4C |
55BFA8EB |
|
E11DCFBE |
F8A48AAE |
8AAEF8A4 |
|
82B860F7 |
08169853 |
|
E77195DF |
94A32A9E |
9E94A32A |
|
08B159F3 |
9625FAD9 |
Ciphertext: 0D 10 D3 8B 55 BF A8 EB 08 16 98 53 96 25 FA D9.
The state value of each step will be the opposite of the encryption state value. Again, a higher-level description of the decryption algorithm is given in Algorithm 6.3.
Algorithm 6.3: Decryption (CipherText)
Begin
State = CipherText
1. KeyExpansion
2. AddRoundKey (State, ExpandedKey[0])
3. for r ← (Nr - 1) to 1
a. InverseShiftRows (State)
b. InverseSubBytes (State, S-box)
c. AddRoundKey (State, ExpandedKey[r])
d. InverseMixColumns (State)
end for
4. InverseSubBytes (State, S-box)
5. InverseShiftRows (State)
6. AddRoundKey (State, ExpandedKey[Nr])
out = PlainText
End
In our implementation, there is no restriction on key selection; no weak or semiweak key has been identified for this AES implementation. The implementation here covers only electronic code block (ECB) encryption mode.
Actually, AES has many pros rather than noticeable cons. As AES was developed after DES, all known attacks on DES have been tested on AES, and all the test results were satisfactory. AES is more secure to brute-force attack than DES because of its larger key size. AES is not prone to statistical attacks, and it has been demonstrated that it is not possible with common techniques to do statistical analysis of ciphertext in AES. As yet, there are no differential and linear attacks on AES. The best part of AES is that the algorithms used in it are so simple that they can be easily implemented using cheap processors and a minimum amount of memory.
On the other hand, AES needs more processing and more rounds of communication than DES, and we can hardly tell this is AES’s disadvantage.
#include<iostream>
#include<vector>
#include<fstream>
#include<string>
#include<sstream>
using namespace std;
#define word unsigned int
#define byte unsigned char
class AES
{
vector<word> ExpandedKey;
int Nk,//width of key block
Nr,//number of round
Nb;//block size
static const byte S_Box 256];
static const byte Si_Box 256];
static const byte Rcon[30];
static const byte ColMixMatrix[4][4];
static const byte InvColMixMatrix[4][4];
static const byte AlogTable[256];
static const byte LogTable[256];
string cipherText;
byte state[4][4];
#ifdef _KEY_TEST_
fstream in;
#endif
#ifdef _TEST_STATE_
fstream stest_fin;
#endif
byte Mul(byte a, byte b);
void MixColumns();
void ShiftRows();
void SubBytes();
byte SubByte(byte oneByte);
word SubWord(word val);
word RotWord(word val);
void InvMixColumns();
void InvShiftRows();
byte InvSubByte(byte oneByte);
void InvSubBytes();
void AddRoundKey(int roundNo);
void KeyExpansion(string key);
string ToString();
public:
static enum KeySize {AES128 = 128, AES192 = 192,
AES256 = 256};
AES(string key, int bitSize);
~AES();
void Encrypt(string plainText);
string GetCipherText();
void Decrypt(string cipherText);
};
#include"AES.h"
byte AES::Mul(byte a, byte b)
{
if(a && b)
return AlogTable[((unsigned char)
LogTable[a] + (unsigned char)
LogTable[b])%255];
return 0;
}
void AES::InvMixColumns()
{
byte temp[4];
for(int c = 0; c < Nb; c ++)
{
//4 rows and Nb columns to store temp mix
col value
for(int r = 0; r < 4; r ++)
{
temp[r] = Mul(InvColMixMatrix[r][0],
(state[0][c]) )
^ Mul(InvColMixMatrix[r]
[1],(state[1][c]))
^ Mul(InvColMixMatrix[r]
[2],(state[2][c]))
^ Mul(InvColMixMatrix[r]
[3],(state[3][c]));
}
state[0][c] = temp[0];
state[1][c] = temp[1];
state[2][c] = temp[2];
state[3][c] = temp[3];
}
}
void AES::MixColumns()
{
byte temp[4];
for(int c = 0; c < Nb; c ++)
{
//4 rows and Nb columns to store temp mix
//col value
for(int r = 0; r < 4; r ++)
{
temp[r] = Mul(ColMixMatrix[r][0],
(state[0][c]) )
^ Mul(ColMixMatrix[r]
[1],(state[1][c]))
^ Mul(ColMixMatrix[r]
[2],(state[2][c]))
^ Mul(ColMixMatrix[r]
[3],(state[3][c]));
}
state[0][c] = temp[0];
state[1][c] = temp[1];
state[2][c] = temp[2];
state[3][c] = temp[3];
}
}
void AES::InvShiftRows()
{
//row is always 4
for(int r = 0; r < 4; r ++)
{
byte temp[4];
temp[0] = state[r][0];
temp[1] = state[r][1];
temp[2] = state[r][2];
temp[3] = state[r][3];
for(int c = 0; c < Nb; c ++)
{
state[r][(r+c)% Nb] = temp[c];
}
}
}
void AES::ShiftRows()
{
//row is always 4
for(int r = 0; r < 4; r ++)
{
byte temp[4];
for(int c = 0; c < Nb; c ++)
{
temp[c] = state[r][(r+c)% Nb];
}
//temp[0] = state[r][(r+0)% Nb];
//temp[1] = state[r][(r+1) % Nb];
//temp[2] = state[r][(r+2) % Nb];
//temp[3] = state[r][(r+3) % Nb];
state[r][0] = temp[0];
state[r][1] = temp[1];
state[r][2] = temp[2];
state[r][3] = temp[3];
}
}
byte AES::InvSubByte(byte oneByte)
{
//one byte represent in hex (xy) x is row
//index and y is column index
return Si_Box[oneByte];
}
void AES::InvSubBytes()
{
for(int i = 0; i < 4; i ++)
{
for(int j = 0; j < Nb; j ++)
{
state[i][j] = InvSubByte(state[i][j]);
}
}
}
void AES::SubBytes()
{
for(int i = 0; i < 4; i ++)
{
for(int j = 0; j < Nb; j ++)
{
state[i][j] = SubByte(state[i][j]);
}
}
}
byte AES::SubByte(byte oneByte)
{
//one byte represent in hex (xy) x is row
//index and y is column index
return S_Box[oneByte];
}
word AES::SubWord(word val)
{
byte oneByte;
word res = 0;
for(int i = 0; i< 4; i ++)
{
res = res << 8;
oneByte = (val >> 24) & 0xFF;
res = res | SubByte(oneByte);
val = val << 8;
}
return res;
}
word AES::RotWord(word val)
{
word res = val << 8;
res = res | (val >> 24);
return res;
}
void AES::AddRoundKey(int roundNo)
{
for(int col = 0; col < Nb; col++)
{
word roundKeyVal = ExpandedKey
[(roundNo*Nb)+col];
for(int row = 3; row > = 0; row— )
{
state[row][col] ^ = (roundKeyVal &0xFF);
roundKeyVal = roundKeyVal >> 8;
}
}
}
AES::~AES()
{
#ifdef _KEY_TEST_
if(in)
{
in.close();
}
#endif
#ifdef _TEST_STATE_
if(stest_fin)
stest_fin.close();
#endif
}
AES::AES(string key, int bitSize)
{
Nr = bitSize/32 + 6;
Nk = bitSize/32;
Nb = 4;//always 4
ExpandedKey.resize(Nk*(Nr+1));
#ifdef _TEST_STATE_
stest_fin.open("128_enc_test.txt",ios::in);
if(!stest_fin )
{
cout << "Cannot not open" << endl;
exit(1);
}
#endif//_Debug_
#ifdef _KEY_TEST_
in.open("128_key_test.txt",ios::in);
if(!in )
{
cout << "Cannot not open" << endl;
exit(1);
}
#endif//_Debug_
KeyExpansion(key);
}
void AES::KeyExpansion(string key)
{
word temp;
for(int i = 0; i < Nk; i ++)
{
ExpandedKey [i] = ((unsigned char) key[4*i]
<< 24) |
((unsigned char)
key[4*i+1] << 16) |
((unsigned char)
key[4*i+2]<<8) |
((unsigned char)
key[4*i+3]);
cout << hex << ExpandedKey[i] << endl;
}
for(int i = Nk; i < Nb*(Nr+1); i++)
{
temp = ExpandedKey[i-1];
if(i% Nk = = 0)
{
temp = SubWord(RotWord(temp)) ^
(Rcon[i/Nk] << 24);
}
else if(Nk >6 && i%Nk = = 4)
{
temp = SubWord(temp);
}
ExpandedKey[i] = ExpandedKey[i-Nk] ^ temp;
#ifdef _KEY_TEST_
int x;
string inpHexVal;
std::stringstream exKeyHexVal;
in >> x >> inpHexVal;
exKeyHexVal << hex <<
ExpandedKey[i];
if(x == i && inpHexVal ==
exKeyHexVal.str() && 0)
cout << i << " : ok " << endl;
else
{
temp = ExpandedKey[i-1];
if(i% Nk = = 0)
{
ofstream out ("keyval.
txt", ios::app);
out << dec <<i << ":not
ok:" << endl;
out << "temp:" <<hex <<
temp << endl;
out << "rot:" <<hex <<
RotWord(temp) << endl;
out << "sub:" <<hex <<
SubWord(RotWord(temp))
<< endl;
out << "After xor
Rcon:" <<hex <<
(SubWord(RotWord
(temp))^ (Rcon[i/Nk] <<
24)) << endl;
out << "Rcon :" <<hex
<< (Rcon[i/Nk] <<24) <<
endl;
out << "W[i-nk] :"
<<hex <<
ExpandedKey[i-Nk] <<
endl;
out << "final :" <<hex
<< ExpandedKey[i]
<< " and " << inpHexVal
<<", "<<exKeyHexVal.
str() << endl <<endl <<
endl;
out.close();
}
else if(Nk >6 && i%Nk = = 4)
{
ofstream out ("keyval.
txt", ios::app);
out << i << ": not ok:"
<< endl;
out << "temp : " <<hex
<< temp << endl;
out << "sub : " <<hex
<< SubWord(temp) <<
endl;
out << "final :" <<hex
<< ExpandedKey[i] <<
endl <<endl << endl;
out.close();
}
else
{
ofstream out ("keyval.
txt", ios::app);
out << dec <<i <<
" : not ok : " << endl;
out << "temp : " <<hex
<< temp << endl;
out << "W[i-nk] : "
<<hex <<
ExpandedKey[i-Nk] <<
endl;
out << "final :" <<hex
<< ExpandedKey[i] <<
" and " << inpHexVal
<<", "<<exKeyHexVal.
str() << endl <<endl <<
endl;
}
}
#endif//_DEBUG_
}
}
#ifdef _DEBUG_
void printState()
{
ofstream out("enc_step.txt",ios::app);
for(int i = 0; i< 4; i ++)
{
for(int j = 0; j < Nb; j++)
{
out << hex << (int)
state[i][j] <<" ";
}
out << endl;
}
out << endl << endl;
}
#endif// _DEBUG_
#ifdef _TEST_STATE_
void testState(int round)
{
cout << round << endl;
for(int i = 0; i< 4; i ++)
{
int x;
stest_fin >> x;
for(int j = 0; j < Nb; j++)
{
string inpHexVal;
std::stringstream exKeyHexVal;
stest_fin >> inpHexVal;
exKeyHexVal << hex << (int)
state[i][j];
if(x = = round && inpHexVal = =
exKeyHexVal.str())
cout << " ok ";
else
{
cout << " not ok " <<
inpHexVal << " " <<
exKeyHexVal.str() << endl;
}
}
cout << endl;
}
cout << endl << endl;
}
#endif//_TEST_STATE_
void AES::Encrypt(string plainText)
{
if((plainText.length()% (4*Nb)) ! = 0)
plainText.append((4*Nb) - (plainText.
length()%(4*Nb)),' '),
int count = 0;
while (count < (plainText.length()))
{
//copy one block into state
for(int c = 0; c <Nb; c++)
{
for(int r = 0; r< 4; r ++)
state[r][c] =
plainText[count+(c*Nb)+r];
}
AddRoundKey(0);
#ifdef _DEBUG_
cout << "After Add round Key 0" << endl;
printState();
#endif//_DEBUG_
int i;
for(i = 1; i < Nr; i ++)
{
#ifdef _TEST_STATE_
cout << i << endl;
testState(i);
#endif//_TEST_STATE_
SubBytes();
#ifdef _DEBUG_
cout << "After Subbytes "<< dec<<
i << endl;
printState();
#endif//_DEBUG_
ShiftRows();
#ifdef _DEBUG_
cout << "After ShifRows "<< dec<<
i << endl;
printState();
#endif//_DEBUG_
MixColumns();
#ifdef _DEBUG_
cout << "After MixColumns "<<
dec<< i << endl;
printState();
#endif//_DEBUG_
AddRoundKey(i);
#ifdef _DEBUG_
cout << "Add round Key " << i <<
endl;
printState();
#endif//_DEBUG_
//exit (1);
}
SubBytes();
#ifdef _DEBUG_
cout << "Round Subbytes"<< dec<<
i << endl;
printState();
#endif//_DEBUG_
ShiftRows();
#ifdef _DEBUG_
cout << "Round ShiftRows"<< dec<<
i << endl;
printState();
#endif//_DEBUG_
AddRoundKey(Nr);
#ifdef _DEBUG_
cout << "Add round Key " << i <<
endl;
printState();
#endif//_DEBUG_
#ifdef _TEST_STATE_
//testState(i);
printState();
#endif//_TEST_STATE_
cipherText = cipherText + ToString();
count+ = 4*Nb;
}
}
string AES::GetCipherText()
{
return cipherText;
}
string AES::ToString()
{
string str;
for(int c = 0;c<Nb; c ++)
{
for(int r = 0; r< Nb; r++)
{
str.push_back(state[r][c]);
}
}
return str;
}
void AES::Decrypt(string cipherText)
{
if((cipherText.length()% (4*Nb)) ! = 0)
cipherText.append((4*Nb) - (cipherText.
length()%(4*Nb)),' '),
int count = 0;
while (count < (cipherText.length()))
{
//copy one block into state
for(int c = 0; c <Nb; c++)
{
for(int r = 0; r< 4; r ++)
state[r][c] =
cipherText[count+(c*Nb)+r];
}
AddRoundKey(Nr);
#ifdef _DEBUG_D_
cout << "After Add round Key 0" << endl;
printState();
#endif//_DEBUG_
int i;
for(i = Nr-1; i>0; i— )
{
#ifdef _TEST_STATE_
cout << i << endl;
testState(i);
#endif//_TEST_STATE_
InvShiftRows();
#ifdef _DEBUG_D_
cout << "After ShiftRows "<< dec<<
i << endl;
printState();
#endif//_DEBUG_
InvSubBytes();
#ifdef _DEBUG_D_
cout << "After Subbytes "<< dec<<
i << endl;
printState();
#endif//_DEBUG_
AddRoundKey(i);
#ifdef _DEBUG_D_
cout << "Add round Key " << i <<
endl;
printState();
#endif//_DEBUG_
InvMixColumns();
#ifdef _DEBUG_D_
cout << "After MixColumns "<<
dec<< i << endl;
printState();
#endif//_DEBUG_
}
InvSubBytes();
#ifdef _DEBUG_D_
cout << "Round Subbytes"<< dec<<
i << endl;
printState();
#endif//_DEBUG_
InvShiftRows();
#ifdef _DEBUG_D_
cout << "Round ShiftRows"<< dec<<
i << endl;
printState();
#endif//_DEBUG_
AddRoundKey(0);
#ifdef _DEBUG_D_
cout << "Add round Key " << i <<
endl;
printState();
#endif//_DEBUG_
#ifdef _TEST_STATE_
//testState(i);
printState();
#endif//_TEST_STATE_
count+ = 4*Nb;
}
}
const byte AES::LogTable[256] = {
0, 0, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51,
238, 223, 3,
100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8,
200, 248, 105, 28, 193,
125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166,
114, 154, 201, 9, 120,
101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69,
53, 147, 218, 142,
150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210,
241, 64, 70, 131, 56,
102, 221, 253, 48, 191, 6, 139, 98, 179, 37, 226,
152, 34, 136, 145, 16,
126, 110, 72, 195, 163, 182, 30, 66, 58, 107, 40,
84, 250, 133, 61, 186,
43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172,
229, 243, 115, 167, 87,
175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233,
213, 231, 230, 173, 232,
44, 215, 117, 122, 235, 22, 11, 245, 89, 203, 95,
176, 156, 169, 81, 160,
127, 12, 246, 111, 23, 196, 73, 236, 216, 67, 31,
45, 164, 118, 123, 183,
204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161,
108, 170, 85, 41, 157,
151, 178, 135, 144, 97, 190, 220, 252, 188, 149,
207, 205, 55, 63, 91, 209,
83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93,
86, 242, 211, 171,
68, 17, 146, 217, 35, 32, 46, 137, 180, 124, 184,
38, 119, 153, 227, 165,
103, 74, 237, 222, 197, 49, 254, 24, 13, 99, 140,
128, 192, 247, 112, 7
};
const byte AES::AlogTable[256] =
{
1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150,
161, 248, 19, 53,
95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10,
30, 34, 102, 170,
229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217,
112, 144, 171, 230, 49,
83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184,
211, 110, 178, 205,
76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241,
8, 24, 40, 120, 136,
131, 158, 185, 208, 107, 189, 220, 127, 129, 152,
179, 206, 73, 219, 118, 154,
181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39,
105, 187, 214, 97, 163,
254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147,
174, 233, 32, 96, 160,
251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50,
86, 250, 21, 63, 65,
195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44,
116, 156, 191, 218, 117,
159, 186, 213, 100, 172, 239, 42, 126, 130, 157,
188, 223, 122, 142, 137, 128,
155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111,
177, 200, 67, 197, 84,
252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153,
176, 203, 70, 202,
69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62,
66, 198, 81, 243, 14,
18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133,
148, 167, 242, 13, 23,
57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108,
180, 199, 82, 246, 1
};
const byte AES::Si_Box 256] =
{
82, 9, 106, -43, 48, 54, -91, 56, -65, 64, -93,
-98, -127, -13, -41, -5,
124, -29, 57, -126, -101, 47, -1, -121, 52, -114,
67, 68, -60, -34, -23, -53,
84, 123, -108, 50, -90, -62, 35, 61, -18, 76, -107,
11, 66, -6, -61, 78,
8, 46, -95, 102, 40, -39, 36, -78, 118, 91, -94,
73, 109, -117, -47, 37,
114, -8, -10, 100, -122, 104, -104, 22, -44, -92,
92, -52, 93, 101, -74, -110,
108, 112, 72, 80, -3, -19, -71, -38, 94, 21, 70,
87, -89, -115, -99, -124,
-112, -40, -85, 0, -116, -68, -45, 10, -9, -28, 88,
5, -72, -77, 69, 6,
-48, 44, 30, -113, -54, 63, 15, 2, -63, -81, -67,
3, 1, 19, -118, 107,
58, -111, 17, 65, 79, 103, -36, -22, -105, -14,
-49, -50, -16, -76, -26, 115,
-106, -84, 116, 34, -25, -83, 53, -123, -30, -7,
55, -24, 28, 117, -33, 110,
71, -15, 26, 113, 29, 41, -59, -119, 111, -73, 98,
14, -86, 24, -66, 27,
-4, 86, 62, 75, -58, -46, 121, 32, -102, -37, -64,
-2, 120, -51, 90, -12,
31, -35, -88, 51, -120, 7, -57, 49, -79, 18, 16,
89, 39, -128, -20, 95,
96, 81, 127, -87, 25, -75, 74, 13, 45, -27, 122,
-97, -109, -55, -100, -17,
-96, -32, 59, 77, -82, 42, -11, -80, -56, -21, -69,
60, -125, 83, -103, 97,
23, 43, 4, 126, -70, 119, -42, 38, -31, 105, 20,
99, 85, 33, 12, 125
};
const byte AES::S_Box 256] =
{
99, 124, 119, 123, -14, 107, 111, -59, 48, 1, 103,
43, -2, -41, -85, 118,
-54, -126, -55, 125, -6, 89, 71, -16, -83, -44,
-94, -81, -100, -92, 114, -64,
-73, -3, -109, 38, 54, 63, -9, -52, 52, -91, -27,
-15, 113, -40, 49, 21,
4, -57, 35, -61, 24, -106, 5, -102, 7, 18, -128,
-30, -21, 39, -78, 117,
9, -125, 44, 26, 27, 110, 90, -96, 82, 59, -42,
-77, 41, -29, 47, -124,
83, -47, 0, -19, 32, -4, -79, 91, 106, -53, -66,
57, 74, 76, 88, -49,
-48, -17, -86, -5, 67, 77, 51, -123, 69, -7, 2,
127, 80, 60, -97, -88,
81, -93, 64, -113, -110, -99, 56, -11, -68, -74,
-38, 33, 16, -1, -13, -46,
-51, 12, 19, -20, 95, -105, 68, 23, -60, -89, 126,
61, 100, 93, 25, 115,
96, -127, 79, -36, 34, 42, -112, -120, 70, -18,
-72, 20, -34, 94, 11, -37,
-32, 50, 58, 10, 73, 6, 36, 92, -62, -45, -84, 98,
-111, -107, -28, 121,
-25, -56, 55, 109, -115, -43, 78, -87, 108, 86,
-12, -22, 101, 122, -82, 8,
-70, 120, 37, 46, 28, -90, -76, -58, -24, -35, 116,
31, 75, -67, -117, -118,
112, 62, -75, 102, 72, 3, -10, 14, 97, 53, 87, -71,
-122, -63, 29, -98,
-31, -8, -104, 17, 105, -39, -114, -108, -101, 30,
-121, -23, -50, 85, 40, -33,
-116, -95, -119, 13, -65, -26, 66, 104, 65, -103,
45, 15, -80, 84, -69, 22
};
const byte AES::Rcon[30] =
{
0,1, 2, 4, 8, 16, 32,
64, -128, 27, 54, 108, -40,
-85, 77, -102, 47, 94, -68,
99, -58, -105, 53, 106, -44,
-77, 125, -6, -17, -59
};
const byte AES::ColMixMatrix[4][4] =
{
2, 3,1, 1,
1, 2, 3, 1,
1, 1, 2, 3,
3, 1, 1, 2
};
const byte AES::InvColMixMatrix[4][4] =
{
0x0E, 0x0B,0x0D, 0x09,
0x09, 0x0E, 0x0B, 0x0D,
0x0D, 0x09, 0x0E, 0x0B,
0x0b, 0x0D, 0x09, 0x0E
};
#include "AES.h"
int main(void)
{
//////////////////////
///Keys test vector
//////////////////////
//128
//char a[] = {0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0
xa6,0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0
x3c,' '};
char a[] = {0x1a,0x91,0xf7,0x20,0x5e,0x45,0x67,0
x06,0xa2,0x5b,0x66,0xde,0x5f,0x14,0x59
,0x88,' '};
//192
//char a[] = {0x8e,0x73,0xb0,0xf7,0xda,0x0e,0x64,0
x52,0xc8,0x10,0xf3,0x2b,0x80,0x90,0x79,0xe5,0x62
,0xf8,0xea,0xd2,0x52,0x2c,0x6b,0x7b,' '};
//256
//char a[] = {0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0
xbe,0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81,0x1f
,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7,0x2d,0x98,0x
10,0xa3,0x09,0x14,0xdf,0xf4,' '};
/////////////////////
//Plain Text test vector
////////////////////
//char b[] = {0x32,0x43,0xf6,0xa8,0x88,0x5a,0x30,0
x8d,0x31,0x31,0x98,0xa2,0xe0,0x37,0x07
,0x34,' '};
//73, 74, 72. 69, 6e, 67, 20. 32, 20, 65,
6e,6372797074
char b[] = {0x73, 0x74, 0x72,0x69, 0x6e, 0x67,
0x20, 0x32, 0x20, 0x65, 0x6e, 0x63, 0x72, 0x79,
0x70, 0x74};
string key;
string text;
for(int i = 0; i < 16;i++)
{
key.push_back(a[i]);
text.push_back(b[i]);
}
AES obj (key, AES::KeySize::AES128);
//obj.KeyExpansion(key);
obj.Encrypt(text);
obj.Decrypt(obj.GetCipherText());
return 0;
}
AES was chosen as the new standard for several reasons. The purpose was to create a new algorithm that is resistant to known attacks and more reliable, as well as faster and simpler, than the existing ones, while also being implemented easily with hardware and software, including restricted environments. It is very clear that AES has satisfied all the conditions with its simple and easy implementation without compromising the security aspect. AES is more versatile, with its variable key size and block size. It was originally designed for nonclassified U.S. government information, but due to its success, AES-256 is usable for top secret government information. As of today, no successful attack on AES has been detected. This reflects how successful AES is in its categories.
3.12.76.164