Summary of a.
The U.S. government opened a competition for more efficient and secure alternatives to DES encryption on September 12, 1997. Fifteen algorithms were selected in the first round, and five were finalists: MARS, RC6, Rijndael, Serpent, and Twofish. The Rijndael algorithm was selected after three more years of validation, evaluation and public discussion.
The Rijndael algorithm was selected as AES because of its security, good performance, high efficiency and practical flexibility.
Rijndael algorithm supports a variety of groups and key length, ranging from 128-256, all multiples of 32 can support the minimum of 128 bits, the maximum of 256 bits. AES standard supports a fixed group size of 128 bits, and the key length has three choices: 128, 192, and 256 bits.
Two. AES algorithm mathematical basis
Many operations in Rijndaels’ algorithm are defined in terms of bytes and 4-byte words. Think of a byte as an element in a finite field GF(28). A Finite Field, also known as a Galois Field, is simply a set that meets specific rules. Elements in the set can be added, subtracted, multiplied and divided, and the operation results also belong to this set.
1. The finite field
The base field of AES is the finite field GF(28)
- All 256 values of a byte form a GF(28)
- An eighth-degree reduced polynomial over a GF(2) yields a GF(28)
- All the elements of GF(28) form an additive Abelian group, a linear space.
- The non-zero elements of GF(28) form the multiplicative cyclic group.
2. Representation of AES over finite fields
There are many ways to represent the elements on the finite field GF(28). For convenience, Rijndaels algorithm adopts polynomial representation. Here are some definitions related to the return representation method
Definition 1: A byte consisting of bits b7b6b5b4b3b2b1b0 can be represented as a binary polynomial with coefficients (0, 1) : b7X7 + b6X6 + b5X5 + b4X4 + b3X3 + b2X2 + b1X + B0
Example: Example: the polynomial for byte 57 = 01010111 is expressed as:
Definition 2: The addition on GF(28) is defined as the addition of binary polynomials whose coefficients are incremented by bit modulo 2.
Example: 57+83 = D4 is equivalent to
Definition 3: Multiplication on GF(28) is defined as the product module of a binary polynomial an irreducible polynomial of degree 8
The hexadecimal expression of its coefficient is 11B, for example: 57×83 = C1 is equivalent to
Definition 4: In GF(28), the binary polynomial b(x) satisfies the binary polynomial whose multiplicative inverse is equation A (x)b(x) mod m(x) = 1.
Definition 5: In GF(28), the multiplication function xtime(b(x)) is defined as x·b(x) mod m(x). If b7=1, then m(x) is subtracted. If GF(28) is added, then m(x) is added. Ex. :
3. Word representation and operation of AES
3.1 words said
The units of AES data processing are bytes and words. A word consists of four bytes and is expressed as a polynomial whose coefficients are taken from GF(28) of less than four degrees, for example: the word 57 83 4A D1 is equivalent to
3.2. The word operations
The word operation is based on the above rules for AES in GF(28).
Word addition: two polynomial coefficients are added by bit modulo 2
Word multiplication: Let a and C be two words, a(x) and c(x) be their word polynomial, AES defines the product b of a and C as
For example, suppose a(x), C (x) and b(x) are respectively shown below (Figure 2-1), and the expression group (Figure 2-1) can be obtained by b(x) = a(x) C (x) mod x4+1
Written in matrix form as shown below (Figure 2-3), x4+1 is a reducible polynomial, the word C (x) does not necessarily have an inverse, but the C (x) chosen by AES does,
Thus, the expression of B (x) can be represented by the above matrix (FIG. 2-4), so that the following MixColumns transformation is transformed into matrix multiplication operation.
Word x multiplication:
The matrix form is shown below, because modulo x4+1, the word x multiplication is equivalent to a cyclic shift by byte
Three. AES encryption process
State of 1.
In ADDITION to bytes and words, AES also has a data processing method called state, which is used to store intermediate data during encryption and decryption. It is usually represented by a matrix or two-dimensional array with bytes as elements.
If Nb is used to indicate the number of words in the ciphertext. Nk represents the number of words in the key. Nr represents the number of iteration rounds, so when Nb and Nk are both equal to 4, the state and key array are shown as below (Figure 3-1) and (Figure 3-2) respectively
According to the definition of Rijndael algorithm, the number of encryption rounds will choose different values for different groups and different key lengths
2. Overview of the encryption process
The main steps of THE AES encryption algorithm are as follows
- Round key generation
- Initial round key plus transform: The initial first (NkRound key that is, the master key performs bit xor operations with the initial state
- Standard round (front 9, 11 or 13 rounds) transform:
- The S box transform
- Row shift transformation
- Column mixture transformation
- Round key plus transformation
- Last round (10th, 12th or 14th) change
- The S box transform
- Row shift transformation
- Round key plus transformation
3. AES finite field addition
/** * Addition on finite fields GF(2), xor of < TT >modeSize</tt> bits * Xor corresponding byte in two state arrays *@param first first operand
* @param second second operand
* @return xor result
*/
private short[][] xor(short[][] first, short[][] second) {
short[][] result = new short[first.length][4];
int length = first.length;
for (short i = 0; i < length; i++) {
for (short j = 0; j < length; j++) {
result[i][j] = (short) (first[i][j] ^ second[i][j]); }}return result;
}
Copy the code
4. Round key generation
The round key is obtained through the master key according to the key generation algorithm. Key generation is carried out in two steps: key expansion and round key selection, and follows the following rules:
- The total number of bits of the round key is the product of the length of the plaintext data block plus the number of rounds. For example, for 128-bit packet length and 10-round iteration, the round key length is 128 x (10 + 1) = 1408 bits, or 11 state lengths
- The user key is first extended to an extended key
- Then select the round key from the extended key: The first round key consists of the first Nb words in the extension (i.e. the original master key), and the second round key is the following Nb“, and so on.
4.1. Key extension
The extended key is represented by a one-dimensional array W[Nb*(Nr+1)] of a word element. Put the key in the first Nk word of the array, and the other words are processed from the words that precede it. Nk ≤ 6 and Nk > 6 are divided into two key extension algorithms:
(1) NkKey expansion ≤ 6
- N in the frontkA word is filled with a master key
- Each successive word W[j] is equal to the preceding word W[j-1] and NkThe word W before the positionkXor]
- And for NkBefore xor, perform Rotl transform and ByteSub transform on W[J-1], xor or a round constant Rcon.
Let W = (A, B, C, D), then Rotl(W) = (B, C, D, A). round constant Rcon has nothing to do with Nk, and is defined as:
- Rcon[I] = (RC[I], ’00’, ’00’, ’00’),
- RC [0] = ’01,
- RC[i] = xtime(RC[i-1])
(2) Nk> 6 key extension
Compared with the key extension of Nk ≤ 6, the difference between the key extension of Nk > 6 is that: if the remainder of j divided by Nk = 4, the ByteSub transform is performed on W[J-1] before xOR.
The reason why ByteSub transform is added is that when Nk > 6, the key is very long, and only ByteSub transform is performed on the words at the integer multiple of Nk, which shows that the density of ByteSub transform is relatively thin and the security degree is not strong enough.
4.2. Round key selection
According to the size of the packet, the round key is extracted from the extended key in turn. The first Nb character is used as round key 0, the next Nb character is used as round key 1, and so on
4.3. Code implementation
/** * Round key extension: Expands the 1 state master key into < TT > Rounds + 1</ TT >rounds * generation of round keys *@param originalKey original cipher key
* @return round keys
*/
private short[][] generateRoundKeys(short[][] originalKey) {
short[][] roundKeys = new short[44] [4];
int keyWordCount = originalKey.length;
// 1. copy the original cipher words into the first four words of the roundKeys
System.arraycopy(originalKey, 0, roundKeys, 0, keyWordCount);
// 2. extension from previous word
for (int i = keyWordCount; i < keyWordCount * 11; i++) {
short[] temp = roundKeys[i - 1];
if (i % keyWordCount == 0) {
temp = xor(substituteWord(leftShift(temp)), AESConstants.R_CON[i / keyWordCount]);
}
roundKeys[i] = xor(roundKeys[i - keyWordCount], temp);
}
return roundKeys;
}
Copy the code
5. AES basic transformation
5.1. S-box transformation
A nonlinear transformation acting on each byte of a state, as contrasted with DES
- Because THE AES-126 plaintext data block is 16 bytes, AES uses 16 identical S boxes (actually the same box can be used 16 times); DES uses eight different S-boxes.
- The S-box of AES has 8-bit input and 8-bit output, which is a nonlinear permutation. The S-box of DES has 6-bit input and 4-bit output, which is a kind of nonlinear compression.
The S-box transformation of AES can be performed in the following two steps:
- Replace the input byte with the inverse of its GF(28)
- Apply the following affine transformation to the result above: (with x0– x7As input, y0– y7As output)
Note that:
- The first step of s-box transformation is to replace the byte value with its multiplicative inverse, which is a nonlinear transformation.
- The second step is an affine operation, a linear transformation.
- Since each column of the coefficient matrix contains five ones, it means that changing any one bit of the input will affect five bits of the output to change.
- And since each row of the coefficient matrix has five ones, that means that every bit of the output is associated with five bits of the input.
Code implementation
Substituting table lookup for operation, the operation was separated into substituteState, substituteWord and substituteByte
The fastest way to achieve S-box is to directly calculate the transformation result of S-box and create a table for storage, and directly look up the table when using (table size is 256 bytes). Table lookup is performed by taking the high and low bits of a byte as the row and column numbers respectively. The elements in the table located by the row and column numbers are the replacement bytes. D4 in the left table below,
Use code to do this
Substitute value of a state array using byte as unit * substitute value of a state array using byte as unit *@param state state array to be substituted
* @return substitution result, a new state array
*/
private short[][] substituteState(short[][] state, short[][] substituteTable) {
for (int i = 0; i < state.length; i++) {
for (int j = 0; j < 4; j++) { state[i][j] = substituteByte(state[i][j], substituteTable); }}return state;
}
Substitute all bytes in a word through SBox * substitute all bytes in a word through SBox *@param aWord a word, aka 4 bytes
* @return substitution result, a new and disrupted word
*/
private short[] substituteWord(short[] aWord) {
for (int i = 0; i < 4; i++) {
aWord[i] = substituteByte(aWord[i], AESConstants.SUBSTITUTE_BOX);
}
return aWord;
}
* Substitute value of a byte through <tt>SBox</tt> * substitute value of a byte through <tt>SBox</tt> *@param originalByte byte to be substituted
* @return substitution result, a new byte
*/
private short substituteByte(short originalByte, short[][] substituteTable) {
// low 4 bits in originByte
int low4Bits = originalByte & 0x000f;
// high 4 bits in originByte
int high4Bits = (originalByte >> 4) & 0x000f;
// obtain value in <tt>AESConstants.SUBSTITUTE_BOX</tt>
return substituteTable[high4Bits][low4Bits];
}
Copy the code
5.2. Row shift transformation
The row shift transform circularly shifts the rows of state. Line 0 is unshifted, line 1 is shifted by C1 bytes, line 2 by C2 bytes, and line 3 by C3 bytes. C1, C2, C3 are valued as follows:
Row shift transformation belongs to permutation and linear transformation, and its essence is to disrupt and rearrange data and play a diffusion role.
Code implementation
/** * row shift: Loops the rows of state to the left, < TT >shiftingTable</tt> defines * row shifting operation, rotate over N which is defined in * <tt>AESConstants.SHIFTING_TABLE</tt> bytes of corresponding rows *@param state state array of the original plaintext
* @return a new state array
*/
private static short[][] shiftRows(short[][] state, short[][] shiftingTable) {
short[][] result = new short[state.length][4];
for (int j = 0; j < 4; j++) { // local byte in a word
for (int i = 0; i < state.length; i++) { // local wordresult[i][j] = state[shiftingTable[i][j]][j]; }}return result;
}
Copy the code
5.3. Column mixing transformation
The column mixing transform treats the column of the state as a polynomial A (x) over GF(28), multiplied by a fixed polynomial C (x), modulo x4+1:
Note that:
- The column mixing transformation belongs to the linear transformation and plays the role of diffusion.
- C (x) is coprime with x4 + 1, thus ensuring that c(x) has an inverse polynomial D (x), and c(x)d(x) = 1 mod x4 + 1. Decryption can only be performed correctly if the inverse polynomial D (x) exists
Code implementation
/** * column mixed transformation: matrix multiplication of state array and polynomial equivalent matrix over finite field GF(2) *@paramState State array *@paramTable polynomial equivalent matrix *@returnThe new state of the column mixture transformation */
private short[][] mixColumns(short[][] state, short[][] table) {
short[][] result = new short[state.length][4];
for (int i = 0; i < state.length; i++) {
result[i] = matrixMultiply(state[i], table);
}
return result;
}
/** * The multiplication operation using a multi between a word of a state and an irreducible * polynomial on a finite field GF(2) <tt>C(x)=03x^3+01x^2+01^2+01x+02</tt> which is replaced as a * constant table <tt>AESConstants.CX</tt> * (aes-128: 4x4 x 4x1 = 4x1) *@param aWord a word of a state
* @return multiplication result, a new word
*/
private short[] matrixMultiply(short[] aWord, short[][] table) {
short[] result = new short[4];
for (int i = 0; i < 4; i++) {
result[i] = wordMultiply(table[i], aWord);
}
return result;
}
/** * the multiplication operation using a multi for a finite field GF(2) * between two words *@param firstWord first operand
* @param secondWord second operand
* @return multiplication result, a byte actually
*/
private short wordMultiply(short[] firstWord, short[] secondWord) {
short result = 0;
for (int i=0; i < 4; i++) {
result ^= multiply(firstWord[i], secondWord[i]);
}
return result;
}
/** * Multiplication on a finite field GF(2) using the x sign to run multiplication on a finite field GF(2) using the x sign to run multiplication on a finite field GF(2)@param a an operand of this kind of multiplication
* @param b another operand of this kind of multiplication
* @return multiplication result
*/
private short multiply(short a, short b) {
short temp = 0;
while(b ! =0) {
if ((b & 0x01) = =1) {
temp ^= a;
}
a <<= 1;
if ((a & 0x100) > 0) {
/* judge if a is greater than 0x80, if then subtract a irreducible polynomial which can be substituted by 0x1b cause addition and subtraction are equivalent in this case it's okay to xor 0x1b */
a ^= 0x1b;
}
b >>= 1;
}
return (short) (temp & 0xff);
}
Copy the code
6. External encryption interface
- Convert the plaintext and key as strings to N respectivelybA state of a word length and NkOne word long master key array
- Generates the round key array from the master key array
- It is convenient to convert 2d round key array into 3D array with NkGets the round key in units of word length
- Call the coreEncrypt method to specify the S-box operand table, the CX operand table used in column mixing, and the shift rule table for row transformations per byte
- The final ciphertext state is encoded in Base64
public String encrypt(String plaintext, String key) {
// transfer plaintext and key from one-dimension matrix
// to (data.length / 4) x 4 matrix
short[][] initialPTState = transfer(transferToShorts(plaintext));
short[][] initialKeyState = transfer(transferToShorts(key));
// obtain raw round keys
short[][] rawRoundKeys = generateRoundKeys(initialKeyState);
// make it easier to obtain a whole block of round key in a round transformation
short[][][] roundKeys = transfer(rawRoundKeys);
short[][] finalState = coreEncrypt(initialPTState, roundKeys, AESConstants.SUBSTITUTE_BOX,
AESConstants.CX, AESConstants.SHIFTING_TABLE);
return Base64Util.encode(transfer2Bytes(finalState));
}
Copy the code
7. Core encryption logic
/** * AES core operation, by extracting reversible operations into a reversible matrix as a parameter, so that the method can be reused in encryption/decryption operations *@paramInitialPTState State array of plaintext or ciphertext status *@paramRoundKeys uses an array of roundKeys for encryption and decryption@paramSubstituteTable - S box * to use for add/decrypt@paramMixColumnTable an array * used to replace a reduced polynomial in mixColumnTable@paramShiftingTable The array * used in row transformations to determine the number of bits to move left between words@returnDecrypt result */
private short[][] coreEncrypt(short[][] initialPTState,
short[][][] roundKeys, short[][] substituteTable,
short[][] mixColumnTable, short[][] shiftingTable) {
// Initial round key add, xor operation
short[][] state = xor(roundKeys[0], initialPTState);
// Handle the first nine rounds of transformations
for (int i = 0; i < 9; i++) {
// Replace the bytes in the status array with the corresponding bytes in the s-box
state = substituteState(state, substituteTable);
// Row shift
state = shiftRows(state, shiftingTable);
// Column mix transform
state = mixColumns(state, mixColumnTable);
// round key add transform
state = xor(roundKeys[i + 1], state);
}
// Handle the last round
state = substituteState(state, substituteTable);
state = shiftRows(state, shiftingTable);
state = xor(roundKeys[roundKeys.length - 1], state);
return state;
}
Copy the code
4. Decryption process
Speaking of encryption throughout the entire AES encryption and decryption process, because Rijndael algorithm is not a conjunction operation, so its decryption algorithm and encryption algorithm is different, according to the decryption algorithm should be the inverse of the encryption algorithm, the most direct approach is to put the encryption algorithm in reverse order, then get decryption algorithm, but this is not easy to achieve engineering.
Due to the clever design of Rijndael algorithm, we only need to slightly change the key expansion strategy and transform the basic operation of the encryption algorithm into the inverse transformation to get the decryption algorithm, whose algorithm structure is actually the same as that of the encryption algorithm.
1. AES basic inverse transformation
1.1. AddRoundKey
The inverse of the round key plus transformation is itself, i.e
1.2. ShiftRows
The inverse of the row shift transformation is the last three rows of the state shifted nb-C1, NB-C2, and Nb-C3 bytes respectively.
1.3. MixColumns
Because the column mixing transformation multiplies each column of the state by a fixed polynomial C (x) :
So the inverse of the column mixing transformation is the inverse polynomial d(x) of c(x) multiplied by each column of the state:
1.4. SubBytes
The inverse of the S-box transformation takes an inverse affine transformation and replaces each byte with its inverse in GF(28).
1.5. KeyExpansion
The decryption key extension is different from the encryption key extension. It is defined as follows:
- Key extension using encryption algorithms
- Apply InvMixColumn to all round keys except the first and last round
RoundKey (Nr+1); roundKey(Nr+1);
2. External decryption interface
- Use Base64 encoding to decode the ciphertext and get the initial state to get the key array
- Call the private core decryption function to get the decrypted plaintext state
- Restore the plaintext state to a string (regardless of Chinese encoding)
public String decrypt(String encryptedText, String key) {
short[][] initialTextState = transfer(Base64Util.decodeToShorts(encryptedText));
short[][] initialKeyState = transfer(transferToShorts(key));
short[][] decryptState = coreDecrypt(initialTextState, initialKeyState);
return getOrigin(decryptState);
}
Copy the code
3. Core decryption logic
Obtain the encryption round key inverse transform array, reuse the core encryption function, the main difference lies in the inverse transform, the general steps are as follows
- The round key array is obtained by key extension of encryption algorithm and processed in dimension
- In the middle Nr-1 key performs the inverse column mixture transformation
- For the convenience of operation, the decryption wheel key array obtained in the above steps can be reversed so that the structure of the multiplexed encryption algorithm can be changed
/** * Decryption logic: reuse encryption core function * by extracting reversible operations into reversible matrices@param encryptedTextState initial encrypted text state
* @param keyState initial key state
* @return decrypted state
*/
private short[][] coreDecrypt(short[][] encryptedTextState, short[][] keyState) {
// obtain raw round keys
short[][] rawRoundKeys = generateRoundKeys(keyState);
// make it easier to obtain a whole block of round key in a round transformation
short[][][] roundKeys = transfer(rawRoundKeys);
// Mix the middle 9 keys
for (int i = 1; i < roundKeys.length - 1; i++) {
roundKeys[i] = mixColumns(roundKeys[i], AESConstants.INVERSE_CX);
}
short[][][] inverseRoundKeys = inverseRoundKeys(roundKeys);
return coreEncrypt(encryptedTextState, inverseRoundKeys, AESConstants.
INVERSE_SUBSTITUTE_BOX, AESConstants.INVERSE_CX, AESConstants.INVERSE_SHIFTING_TABLE);
}
/** * [decryption] will decrypt the extended key array reversal, convenient reuse of core encryption operations, *@paramRoundKeys decrypts the extended key array *@returnReversed decryption extended key array */
private short[][][] inverseRoundKeys(short[][][] roundKeys) {
short[][][] result = new short[roundKeys.length][4] [4];
int length = roundKeys.length;
for (int i = 0; i < roundKeys.length; i++) {
result[i] = roundKeys[length - 1 - i];
}
return result;
}
Copy the code
5. Test
@Test
public void testAES(a) throws UnsupportedEncodingException {
String plaintext = "passwordTextCase", key = "simpleKeyCase123";
CipherService aesService = new AESCipherService();
String encryptedText = aesService.encrypt(plaintext, key);
ArrayUtil.printInfo("encrypted text", encryptedText, false);
aesService.decrypt(encryptedText, key);
}
Copy the code
1. Encryption result
##################### encryption #####################
plaintext text passwordTextCase
key text simpleKeyCase123
initial plaintext state 70617373776f72645465787443617365
initial key state 73696d706c654b657943617365313233
RoundKeys
[RoundKey 1] 73696d706c654b657943617365313233
[RoundKey 2] b54aae3dd92fe558a06c842bc55db618
[RoundKey 3] fb04039b222be6c3824762e8471ad4f0
[RoundKey 4] 5d4c8f3b7f6769f8fd200b10ba3adfe0
[RoundKey 5] d5d26ecfaab5073757950c27edafd3c7
[RoundKey 6] bcb4a89a1601afad4194a38aac3b704d
[RoundKey 7] 7ee54b0b68e4e4a62970472c854b3761
[RoundKey 8] 8d7fa49ce59b403acceb071649a03077
[RoundKey 9] ed7b51a708e0119dc40b168b8dab26fc
[RoundKey 10] 948ce1fa9c6cf0675867e6ecd5ccc010
[RoundKey 11] e9362bf9755adb9e2d3d3d72f8f1fd62
N = 1
SubBytes 7b30727baf67127cd8f7d4c5f75383b1
ShiftRows 7b67d4b1aff7837bd853727cf73012c5
MixColumns 3a636747bfbfc8685094ebaa7264b7b1
RoundKey b54aae3dd92fe558a06c842bc55db618
AddRoundKeys 8f29c97a66902d30f0f86f81b73901a9
N = 2
SubBytes 73a5ddda3360d8048c41a80ca9127cd3
ShiftRows 7360a8d333417cda8c12dd04a9a5d80c
MixColumns 3d8336e003efffc7ecd033486987b385
RoundKey fb04039b222be6c3824762e8471ad4f0
AddRoundKeys c687357b21c419046e9751a02e9d6775
N = 3
SubBytes b4179621fd1cd4f29f88d1e0315e859d
ShiftRows b41cd19dfd8885219f5e96f23117d4e0
MixColumns 1b79ad2bc6430753a370fb8d6f98ae4b
RoundKey 5d4c8f3b7f6769f8fd200b10ba3adfe0
AddRoundKeys 46352210b9246eab5e50f09dd5a271ab
N = 4
SubBytes 5a9693ca56369f6258538c5e033aa362
ShiftRows 5a368c625653a3ca583a936203969f5e
MixColumns 00dbc99030c41d850fe0f98566d052b0
RoundKey d5d26ecfaab5073757950c27edafd3c7
AddRoundKeys d509a75f9a711ab25875f5a28b7f8177
N = 5
SubBytes 03015ccfb8a3a2376a9de63a3dd20cf5
ShiftRows 03a3e6f5b89d0ccf6ad25c373d01a23a
MixColumns eb9a73b1144277c7d206595ee1f82d90
RoundKey bcb4a89a1601afad4194a38aac3b704d
AddRoundKeys 572edb2b0243d86a9392fad44dc35ddd
N = 6
SubBytes 5b31b9f1771a6102dc4f2d48e32e4cc1
ShiftRows 5b1a2dc1774f4cf1dc2eb902e3316148
MixColumns 74d9434382cca8636a529deca76ac8fe
RoundKey 7ee54b0b68e4e4a62970472c854b3761
AddRoundKeys 0a3c0848ea284cc54322dac02221ff9f
N = 7
SubBytes 67eb3052873429a61a9357ba93fd16db
ShiftRows 673457db879316521afd30a693eb29ba
MixColumns 1e2d8b67ffd2ceb3be0d76b4889fff03
RoundKey 8d7fa49ce59b403acceb071649a03077
AddRoundKeys 93522ffb1a498e8972e671a2c13fcf74
N = 8
SubBytes dc00150fa23b19a7408ea33a78758a92
ShiftRows dc3ba392a28e8a0f407515a77800193a
MixColumns dfc617d8532f32e7ad32edf5d36904e5
RoundKey ed7b51a708e0119dc40b168b8dab26fcAddRoundKeys 32bd467f5bcf237a6939fb7e5ec22219 N = 9 SubBytes 237a5ad2398a26daf9120ff3582593d4 ShiftRows 238a0fd4391293d2f9255ada587a26f3 MixColumns 18e9d05305617b7506871dc0eb356049 RoundKey 948ce1fa9c6cf0675867e6ecd5ccc010 AddRoundKeys 8c6531a9990d8b125ee0fb2c3ef9a059 N = 10 SubBytes 644dc7d3eed73dc958e10f71b299e0cb ShiftRows 64d70fcbeee1e0d35899c7c9b24d3d71 RoundKey e9362bf9755adb9e2d3d3d72f8f1fd62 AddRoundKeys 8de124329bbb3b4d75a4fabb4abcc013 encrypted text jeEkMpu7O011pPq7SrzAEw==Copy the code
2. Decrypt the result
##################### decryption #####################
encrypted text jeEkMpu7O011pPq7SrzAEw==
key text simpleKeyCase123
initial encrypted state 8de124329bbb3b4d75a4fabb4abcc013
initial key state 73696d706c654b657943617365313233
RoundKeys
[RoundKey 1] 73696d706c654b657943617365313233
[RoundKey 2] b54aae3dd92fe558a06c842bc55db618
[RoundKey 3] fb04039b222be6c3824762e8471ad4f0
[RoundKey 4] 5d4c8f3b7f6769f8fd200b10ba3adfe0
[RoundKey 5] d5d26ecfaab5073757950c27edafd3c7
[RoundKey 6] bcb4a89a1601afad4194a38aac3b704d
[RoundKey 7] 7ee54b0b68e4e4a62970472c854b3761
[RoundKey 8] 8d7fa49ce59b403acceb071649a03077
[RoundKey 9] ed7b51a708e0119dc40b168b8dab26fc
[RoundKey 10] 948ce1fa9c6cf0675867e6ecd5ccc010
[RoundKey 11] e9362bf9755adb9e2d3d3d72f8f1fd62
inverse roundKeys
[RoundKey 1] e9362bf9755adb9e2d3d3d72f8f1fd62
[RoundKey 2] 708e03febe111cd46ee2ba036852f407
[RoundKey 3] 513f2d23ce9f1f2ad0f3a6d706b04e04
[RoundKey 4] 16b3b0df9fa032091e6cb9fdd643e8d3
[RoundKey 5] de6e462d891382d681cc8bf4c82f512e
[RoundKey 6] 0dc56d9f577dc4fb08df092249e3dada
[RoundKey 7] e0240c6e5ab8a9645fa2cdd9413cd3f8
[RoundKey 8] e0ec63caba9ca50a051a64bd1e9e1e21
[RoundKey 9] a13297635a70c6c0bf86c1b71b847a9c
[RoundKey 10] 1d7fded0fb4251a3e5f60777a402bb2b
[RoundKey 11] 73696d706c654b657943617365313233
N = 1
SubBytes 8c0dfb5999e0a0a95ef931123e658b2c
ShiftRows 8c6531a9990d8b125ee0fb2c3ef9a059
MixColumns 53040c2a87038f0697c7e0d93028d2f4
RoundKey 708e03febe111cd46ee2ba036852f407
AddRoundKeys 238a0fd4391293d2f9255ada587a26f3
N = 2
SubBytes 32cffb195b39227f69c2467a5ebd237e
ShiftRows 32bd467f5bcf237a6939fb7e5ec22219
MixColumns 8d048eb16c1195259086b3707eb0573e
RoundKey 513f2d23ce9f1f2ad0f3a6d706b04e04
AddRoundKeys dc3ba392a28e8a0f407515a77800193a
N = 3
SubBytes 934971741ae6cffb723f2f89c1528ea2
ShiftRows 93522ffb1a498e8972e671a2c13fcf74
MixColumns 7187e7041833245b0491895b45a8c169
RoundKey 16b3b0df9fa032091e6cb9fdd643e8d3
AddRoundKeys 673457db879316521afd30a693eb29ba
N = 4
SubBytes 0a28da9fea22ff48432108c5223c4cc0
ShiftRows 0a3c0848ea284cc54322dac02221ff9f
MixColumns 85746becfe5cce275de232f62b1e3066
RoundKey de6e462d891382d681cc8bf4c82f512e
AddRoundKeys 5b1a2dc1774f4cf1dc2eb902e3316148
N = 5
SubBytes 5743fadd02925d2b93c3db6a4d2ed8d4
ShiftRows 572edb2b0243d86a9392fad44dc35ddd
MixColumns 0e668b6aefe0c834620d551574e278e0
RoundKey 0dc56d9f577dc4fb08df092249e3dada
AddRoundKeys 03a3e6f5b89d0ccf6ad25c373d01a23a
N = 6
SubBytes d571f5779a75815f587fa7b28b091aa2
ShiftRows d509a75f9a711ab25875f5a28b7f8177
MixColumns ba12800c0ceb0aae07985ebb42aa4ca6
RoundKey e0240c6e5ab8a9645fa2cdd9413cd3f8
AddRoundKeys 5a368c625653a3ca583a936203969f5e
N = 7
SubBytes 4624f0abb95071105ea222abd5356e9d
ShiftRows 46352210b9246eab5e50f09dd5a271ab
MixColumns 54f0b2574714202b9a44f24f2f89cac1
RoundKey e0ec63caba9ca50a051a64bd1e9e1e21
AddRoundKeys b41cd19dfd8885219f5e96f23117d4e0 N = 8 SubBytes c6c451752197677b6e9d35042e8719a0 ShiftRows c687357b21c419046e9751a02e9d6775 MixColumns d2523fb06931ba1a33941cb3b221a290 RoundKey a13297635a70c6c0bf86c1b71b847a9c AddRoundKeys 7360a8d333417cda8c12dd04a9a5d80c N = 9 SubBytes 8f906fa966f8017af039c930b7292d81 ShiftRows 8f29c97a66902d30f0f86f81b73901a9 MixColumns 66180a6154b5d2d83da5750b5332a9ee RoundKey 1d7fded0fb4251a3e5f60777a402bb2b AddRoundKeys 7b67d4b1aff7837bd853727cf73012c5 N = 10 SubBytes 030a19561b2641032d501e0126083907 ShiftRows 03081e031b0a39012d26190726504156 RoundKey 73696d706c654b657943617365313233 AddRoundKeys 70617373776f72645465787443617365 plaintext passwordTextCaseCopy the code
6. Summary
This article mainly describes the origin, mathematical principle, encryption and decryption process of AES, and provides sample code snippets. Since I actually wrote this article in October 2018 (see my original blog), many of the mathematical principle details have been almost forgotten. Due to the system change, All the markdown files of the original blog have been lost, so they will not be maintained any more. If there is an opportunity in the future, I will write them here, so I will dig and record them here, hoping that it will be helpful to friends who are learning cryptography.
In addition, the code in the article has been uploaded to Github, interested friends can have a look, if you like, hope to click on the star or fork support.
Reference 7.
- FIPS 197 — Advanced Encryption Standard
- Animation shows AES in action
- Introduction to Cryptography (3rd edition, edited by Zhang Huanguo and Tang Ming, Wuhan University Press)