当前位置:网站首页>[cryptography] AES encryption and decryption
[cryptography] AES encryption and decryption
2022-06-10 08:26:00 【Xiaoyuan Xiaoyuan eats dumplings】
1.AES How it works
Rijndael Is a flexible algorithm , The size of the block is variable (128bit、192bit or 256bit), Key size is variable (128bit、192bit or 256bit), The number of iterations depends on the size of the block and key , Therefore, the number of iterations is variable (10,12 or 14). common Rijndael The structure is shown in the following figure .Rijndael Unlike DES So use substitution and substitution in each phase , It's about replacing multiple loops (Substitution)、 Line shift (ShiftRow)、 Column hybrid (Mixcolumn) And key addition (Key Add) operation . In this paper, the term AES and Rijndael As equivalent , Can be used interchangeably , meanwhile , Unless otherwise specified, assume that the size of the block is 128 position .
Rijndael First, the plaintext is divided into columns by bytes . front 4 Bytes form the first column , Next 4 Bytes make up the second column , And so on , As shown in the figure below . Because the size of the block is 128bit, Then we can form a 4×4 Matrix .
example : Suppose the short message to be sent is :“Bob look at this”. Including spaces , This message happens to be 16 Bytes ( Expressed as ASCII Code for 128bit).
This message is expressed in hexadecimal as :42 6f 62 20 6c 6f 6f 6b 20 61 74 20 74 68 69 73.
It's written in 4×4 The matrix form of is :
( 42 6 c 20 74 6 f 6 f 61 68 62 6 f 74 69 20 6 b 20 73 ) \begin{pmatrix} 42& 6c & 20 & 74\\ 6f& 6f & 61 & 68\\ 62& 6f & 74 & 69\\ 20& 6b & 20 & 73 \end{pmatrix} ⎝⎜⎜⎛426f62206c6f6f6b2061742074686973⎠⎟⎟⎞
2.AES Encryption operation
2.1 Replace operation
Rijndael It USES one S- box ( Not like it DES Use like that 8 individual ).Rijndael Of S- The box is a 16×16 Matrix , As shown in the following code . Each element of the column is used as input to specify S- The address of the box : front 4 Bit specifies S- The line of the box , after 4 Bit specifies S- Columns of boxes . Determined by rows and columns S- The element of the box position replaces the element of the corresponding position in the plaintext matrix .
//S box
const unsigned char SBox[16][16] ={
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
/*0*/{
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76 },
/*1*/{
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0 },
/*2*/{
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15 },
/*3*/{
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75 },
/*4*/{
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84 },
/*5*/{
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf },
/*6*/{
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8 },
/*7*/{
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2 },
/*8*/{
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73 },
/*9*/{
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb },
/*a*/{
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79 },
/*b*/{
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08 },
/*c*/{
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a },
/*d*/{
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e },
/*e*/{
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf },
/*f*/{
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }
};
example : The matrix of the above plaintext is : ( 42 6 c 20 74 6 f 6 f 61 68 62 6 f 74 69 20 6 b 20 73 ) \begin{pmatrix} 42& 6c & 20 & 74\\ 6f& 6f & 61 & 68\\ 62& 6f & 74 & 69\\ 20& 6b & 20 & 73 \end{pmatrix} ⎝⎜⎜⎛426f62206c6f6f6b2061742074686973⎠⎟⎟⎞
after S- After the box is replaced, it becomes ( 2 c 50 b 7 92 a 8 a 8 e f 45 a a a 8 92 f 9 b 7 7 f b 7 8 f ) \begin{pmatrix} 2c & 50 & b7 & 92\\ a8 & a8 & ef & 45\\ aa & a8 & 92 & f9\\ b7 & 7f & b7 & 8f \end{pmatrix} ⎝⎜⎜⎛2ca8aab750a8a87fb7ef92b79245f98f⎠⎟⎟⎞
(0x42 Before 4 Position as 0x04, after 4 Position as 0x02, stay S- Find the corresponding element in the box , Others, and so on )
S- The code for the box replacement operation is as follows :
void SBoxFunc(unsigned char inputText[][4], unsigned char inputTextEncrypt[][4])
{
unsigned int row=0,column=0;
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
row = (inputText[i][j] & 0xF0) >> 4;
column = inputText[i][j]&0x0F;
inputTextEncrypt[i][j] = SBox[row][column];
}
}
}
2.2 Row shift operation
The row shift operation is applied to S- Output of the box , among , Column 4 A row spirals to the left , That is, the first line moves left 0 Bytes , The second line moves left 1 Bytes , The third line moves left 2 Bytes , The fourth line moves left 3 Bytes , As shown in the figure below . As can be seen from the picture , This makes the columns completely rearranged , That is, in each column after the shift , Contains a byte of each column before the shift .
The above text is approved by S- The matrix after box transformation is :
( 2 c 50 b 7 92 a 8 a 8 e f 45 a a a 8 92 f 9 b 7 7 f b 7 8 f ) \begin{pmatrix} 2c & 50 & b7 & 92\\ a8 & a8 & ef & 45\\ aa & a8 & 92 & f9\\ b7 & 7f & b7 & 8f \end{pmatrix} ⎝⎜⎜⎛2ca8aab750a8a87fb7ef92b79245f98f⎠⎟⎟⎞
After the row shift operation , The matrix becomes :
( 2 c 50 b 7 92 a 8 e f 45 a 8 92 f 9 a a a 8 8 f b 7 7 f b 7 ) \begin{pmatrix} 2c & 50 & b7 & 92\\ a8 & ef & 45 & a8\\ 92 & f9 & aa & a8\\ 8f & b7 & 7f & b7 \end{pmatrix} ⎝⎜⎜⎛2ca8928f50eff9b7b745aa7f92a8a8b7⎠⎟⎟⎞
The implementation code of the line shift operation is as follows :
// A formal parameter is a 4×4 Matrix
void ShiftRows(unsigned char inputTextEncrypt [][4])
{
unsigned char temp = 0;
for(int i=1;i<4;i++)
{
for(int j=0;j<i;j++)
{
temp = inputTextEncrypt[i][0];
inputTextEncrypt[i][0] = inputTextEncrypt[i][1];
inputTextEncrypt[i][1] = inputTextEncrypt[i][2];
inputTextEncrypt[i][2] = inputTextEncrypt[i][3];
inputTextEncrypt[i][3] = temp;
}
}
}
2.3 Column mixing operations
The column mixing operation is realized by matrix multiplication . Shifted matrix and fixed matrix ( In hexadecimal ) Multiply , As shown below : ( c 0 c 1 c 3 c 4 ) = ( 02 03 01 01 01 02 03 01 01 01 02 03 03 01 01 02 ) ( b 0 b 1 b 2 b 4 ) \begin{pmatrix} c_0 \\ c_1 \\ c_3 \\ c_4 \end{pmatrix} = \begin{pmatrix} 02 & 03 & 01 & 01\\ 01 & 02 & 03 & 01\\ 01 & 01 & 02 & 03\\ 03 & 01 & 01 & 02 \end{pmatrix} \begin{pmatrix} b_0 \\ b_1 \\ b_2 \\ b_4 \end{pmatrix} ⎝⎜⎜⎛c0c1c3c4⎠⎟⎟⎞=⎝⎜⎜⎛02010103030201010103020101010302⎠⎟⎟⎞⎝⎜⎜⎛b0b1b2b4⎠⎟⎟⎞
Be careful : This operation needs to be done G F ( 2 n ) GF(2^n) GF(2n) On the multiplication of , But because the multiplied factor is three fixed elements 02、03、01, So these multiplication operations are still relatively simple , The modular polynomial used in multiplication is m ( x ) = x 8 + x 4 + x 3 + x + 1 m(x)=x^8+x^4+x^3+x+1 m(x)=x8+x4+x3+x+1. Set a byte as ( b 7 b 6 b 5 b 4 b 3 b 2 b 1 b 0 ) (b_7b_6b_5b_4b_3b_2b_1b_0) (b7b6b5b4b3b2b1b0), Then there are :
( b 7 b 6 b 5 b 4 b 3 b 2 b 1 b 0 ) × ′ 0 1 ′ = ( b 7 b 6 b 5 b 4 b 3 b 2 b 1 b 0 ) ; ( b 7 b 6 b 5 b 4 b 3 b 2 b 1 b 0 ) × ′ 0 2 ′ = ( b 6 b 5 b 4 b 3 b 2 b 1 b 0 0 ) + ( 000 b 7 b 7 0 b 7 b 7 ) ; ( b 7 b 6 b 5 b 4 b 3 b 2 b 1 b 0 ) × ′ 0 3 ′ = ( b 7 b 6 b 5 b 4 b 3 b 2 b 1 b 0 ) × ′ 0 1 ′ ⊕ ( b 7 b 6 b 5 b 4 b 3 b 2 b 1 b 0 ) × ′ 0 2 ′ ; (b_7b_6b_5b_4b_3b_2b_1b_0)\times '01'=(b_7b_6b_5b_4b_3b_2b_1b_0);\\ (b_7b_6b_5b_4b_3b_2b_1b_0)\times '02'=(b_6b_5b_4b_3b_2b_1b_00)+(000b_7b_70b_7b_7);\\ (b_7b_6b_5b_4b_3b_2b_1b_0)\times '03'=(b_7b_6b_5b_4b_3b_2b_1b_0)\times '01'\oplus(b_7b_6b_5b_4b_3b_2b_1b_0)\times '02'; (b7b6b5b4b3b2b1b0)×′01′=(b7b6b5b4b3b2b1b0);(b7b6b5b4b3b2b1b0)×′02′=(b6b5b4b3b2b1b00)+(000b7b70b7b7);(b7b6b5b4b3b2b1b0)×′03′=(b7b6b5b4b3b2b1b0)×′01′⊕(b7b6b5b4b3b2b1b0)×′02′;
These operations ensure that the plaintext bits are highly scrambled after several iterations , It also ensures that there is little correlation between input and output . These are two important characteristics of the security of the algorithm .
example : The matrix after the above row shift operation is : ( 2 c 50 b 7 92 a 8 e f 45 a 8 92 f 9 a a a 8 8 f b 7 7 f b 7 ) \begin{pmatrix} 2c & 50 & b7 & 92\\ a8 & ef & 45 & a8\\ 92 & f9 & aa & a8\\ 8f & b7 & 7f & b7 \end{pmatrix} ⎝⎜⎜⎛2ca8928f50eff9b7b745aa7f92a8a8b7⎠⎟⎟⎞
Mix them in columns , Then there are
( a 6 c 4 6 f c 3 45 32 a 7 8 d 31 94 3 c b 3 4 b 93 d 3 d 8 ) = ( 02 03 01 01 01 02 03 01 01 01 02 03 03 01 01 02 ) ( 2 c 50 b 7 92 a 8 e f 45 a 8 92 f 9 a a a 8 8 f b 7 7 f b 7 ) \begin{pmatrix} a6 & c4 & 6f & c3\\ 45 & 32 & a7 & 8d\\ 31 & 94 & 3c & b3\\ 4b & 93 & d3 & d8 \end{pmatrix} = \begin{pmatrix} 02 & 03 & 01 & 01\\ 01 & 02 & 03 & 01\\ 01 & 01 & 02 & 03\\ 03 & 01 & 01 & 02 \end{pmatrix} \begin{pmatrix} 2c & 50 & b7 & 92\\ a8 & ef & 45 & a8\\ 92 & f9 & aa & a8\\ 8f & b7 & 7f & b7 \end{pmatrix} ⎝⎜⎜⎛a645314bc43294936fa73cd3c38db3d8⎠⎟⎟⎞=⎝⎜⎜⎛02010103030201010103020101010302⎠⎟⎟⎞⎝⎜⎜⎛2ca8928f50eff9b7b745aa7f92a8a8b7⎠⎟⎟⎞
Calculate ( 02 03 01 01 ) ( 2 c a 8 92 8 f ) \begin{pmatrix} 02 & 03 & 01 & 01 \end{pmatrix} \begin{pmatrix} 2c \\ a8 \\ 92 \\ 8f \end{pmatrix} (02030101)⎝⎜⎜⎛2ca8928f⎠⎟⎟⎞
02 × 2 c = 00000010 × 00101100 = 01011000 ⊕ 00000000 = 01011000 ; 03 × a 8 = 02 × a 8 ( 10101000 ) ⊕ 01 × a 8 ( 10101000 ) = 01010000 ⊕ 00011011 ⊕ 10101000 = 11100011 ; 01 × 92 = 10010010 ; 01 × 8 f = 10001111 ; 01011000 ⊕ 11100011 ⊕ 10010010 ⊕ 10001111 = 10100110 = a 6 02\times 2c=00000010\times 00101100=01011000\oplus 00000000=01011000;\\ 03\times a8=02\times a8(10101000)\oplus 01\times a8(10101000)=01010000\oplus 00011011\oplus 10101000=11100011;\\ 01\times 92=10010010;\\ 01\times8f=10001111;\\ 01011000\oplus11100011\oplus10010010\oplus10001111=10100110=a6 02×2c=00000010×00101100=01011000⊕00000000=01011000;03×a8=02×a8(10101000)⊕01×a8(10101000)=01010000⊕00011011⊕10101000=11100011;01×92=10010010;01×8f=10001111;01011000⊕11100011⊕10010010⊕10001111=10100110=a6
This gives the first value a 6 a6 a6, Let's do the rest by ourselves .
Be careful :① ⊕ \oplus ⊕ Is an XOR operation ;② ride 02 The XOR is 000 b 7 b 7 0 b 7 b 7 000b_7b_70b_7b_7 000b7b70b7b7.
The code for the column mixing step is as follows :
// Matrix to multiply
const unsigned char GFMatrix[4][4] = {
{
0x02,0x03,0x01,0x01},
{
0x01,0x02,0x03,0x01},
{
0x01,0x01,0x02,0x03},
{
0x03,0x01,0x01,0x02}
};
// The following is the matrix multiplication operation
unsigned char GFMul01(unsigned char num)
{
return num;
}
unsigned char GFMul02(unsigned char num)
{
unsigned char temp = num>>7&0xFF;
if(temp==0x00)
return num<<1&0xFF;
else if(temp==0x01)
return (num<<1&0xFF)^0x1B;
}
unsigned char GFMul03(unsigned char num)
{
return GFMul01(num)^GFMul02(num);
}
unsigned char GFMulAll(unsigned char num1,unsigned char num2)
{
if(num2==0x01)
return GFMul01(num1);
else if(num2==0x02)
return GFMul02(num1);
else if(num2==0x03)
return GFMul03(num1);
}
// Column mix implementation code
void ColumnMix(unsigned char inputTextEncrypt [][4],unsigned char inputTextColumnMix [][4])
{
for(int j=0;j<4;j++)
{
for(int i=0;i<4;i++)
{
inputTextColumnMix[i][j] = GFMulAll(inputTextEncrypt[0][j],GFMatrix[i][0])^GFMulAll(inputTextEncrypt[1][j],GFMatrix[i][1])^GFMulAll(inputTextEncrypt[2][j],GFMatrix[i][2])^GFMulAll(inputTextEncrypt[3][j],GFMatrix[i][3]);
}
}
}
2.4 Key adding operation
The key addition operation is the last operation in each round , Is to compare the above result with the sub key XOR Logical operations , As shown in the figure below . This completes an iteration of the algorithm .
example : After column mixing , The plaintext matrix becomes :
( a 6 c 4 6 f c 3 45 32 a 7 8 d 31 94 3 c b 3 4 b 93 d 3 d 8 ) \begin{pmatrix} a6 & c4 & 6f & c3\\ 45 & 32 & a7 & 8d\\ 31 & 94 & 3c & b3\\ 4b & 93 & d3 & d8 \end{pmatrix} ⎝⎜⎜⎛a645314bc43294936fa73cd3c38db3d8⎠⎟⎟⎞
Assume that the round key at this time is :
( 01 a 3 90 12 e 1 44 20 11 c c 73 04 a 9 59 06 30 b 4 ) \begin{pmatrix} 01 & a3 & 90 & 12\\ e1 & 44 & 20 & 11\\ cc & 73 & 04 & a9\\ 59 & 06 & 30 & b4 \end{pmatrix} ⎝⎜⎜⎛01e1cc59a3447306902004301211a9b4⎠⎟⎟⎞
Then there are
( a 6 c 4 6 f c 3 45 32 a 7 8 d 31 94 3 c b 3 4 b 93 d 3 d 8 ) X O R ( 01 a 3 90 12 e 1 44 20 11 c c 73 04 a 9 59 06 30 b 4 ) = ( a 7 67 f f d 1 a 4 76 87 9 c f d e 7 38 1 a 12 95 e 3 6 c ) \begin{pmatrix} a6 & c4 & 6f & c3\\ 45 & 32 & a7 & 8d\\ 31 & 94 & 3c & b3\\ 4b & 93 & d3 & d8 \end{pmatrix} XOR \begin{pmatrix} 01 & a3 & 90 & 12\\ e1 & 44 & 20 & 11\\ cc & 73 & 04 & a9\\ 59 & 06 & 30 & b4 \end{pmatrix} = \begin{pmatrix} a7 & 67 & ff & d1\\ a4 & 76 & 87 & 9c\\ fd & e7 & 38 & 1a\\ 12 & 95 & e3 & 6c \end{pmatrix} ⎝⎜⎜⎛a645314bc43294936fa73cd3c38db3d8⎠⎟⎟⎞XOR⎝⎜⎜⎛01e1cc59a3447306902004301211a9b4⎠⎟⎟⎞=⎝⎜⎜⎛a7a4fd126776e795ff8738e3d19c1a6c⎠⎟⎟⎞
a 6 ⊕ 01 = a 7 ; c 4 ⊕ a 3 = 67 ; a6\oplus01=a7;c4\oplus a3=67; a6⊕01=a7;c4⊕a3=67; And so on
The code of key adding operation is as follows :
void RoundKeyXOR(unsigned char inputTextColumnMix [][4],unsigned char RoundKey [][4],unsigned char inputText[][4])
{
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
inputText[i][j] = inputTextColumnMix[i][j]^RoundKey[i][j];
}
}
}
3.AES Key generation for
Keys are grouped by the columns of the matrix , Then add 40 New columns to expand . If the former 4 Column ( That is, the columns given by the key ) by W ( 0 ) W(0) W(0)、 W ( 1 ) W(1) W(1)、 W ( 2 ) W(2) W(2) and W ( 3 ) W(3) W(3), Then the new column is generated recursively .
If i i i No 4 Multiple , So the first i i i The column is determined by the following equation : W ( i ) = W ( i − 4 ) X O R W ( i − 1 ) W(i)=W(i-4) \quad XOR \quad W(i-1) W(i)=W(i−4)XORW(i−1) If i i i yes 4 Multiple , So the first i i i The column is determined by the following equation : W ( i ) = W ( i − 4 ) X O R T [ W ( i − 1 ) ] W(i)=W(i-4) \quad XOR \quad T[W(i-1)] W(i)=W(i−4)XORT[W(i−1)] among T [ W ( i − 1 ) ] T[W(i-1)] T[W(i−1)] yes W ( i − 1 ) W(i-1) W(i−1) A form of transformation , It is implemented in the following way :
(1) Circulate W ( i − 1 ) W(i-1) W(i−1) Element shift , One byte at a time , in other words , a b c d abcd abcd become b c d a bcda bcda( A letter is a byte size ).
(2) Will this 4 Bytes as S- Box input , Output new 4 Bytes e f g h efgh efgh.
(3) Calculate a round of constants r ( i ) = 2 ( i − 4 ) / 4 r(i)=2^{(i-4)/4} r(i)=2(i−4)/4.
(4) This generates the converted columns : [ e X O R r ( i ) , f , g , h ] [e\quad XOR \quad r(i),f,g,h] [eXORr(i),f,g,h].
The first i i i The round key of the round forms a column W ( 4 i ) W(4i) W(4i)、 W ( 4 i + 1 ) W(4i+1) W(4i+1)、 W ( 4 i + 2 ) W(4i+2) W(4i+2) and W ( 4 i + 3 ) W(4i+3) W(4i+3). The process is shown in the figure below :
example : If the initial 128bit The key is ( In hexadecimal ):3ca10b21、57f01916、902e1380 and acc107bd.
that 4 The first initial value is W ( 0 ) = 3 c a 10 b 21 , W ( 1 ) = 57 f 01916 , W ( 2 ) = 902 e 1380 , W ( 3 ) = a c c 107 b d W(0)=3ca10b21,W(1)=57f01916,W(2)=902e1380,W(3)=acc107bd W(0)=3ca10b21,W(1)=57f01916,W(2)=902e1380,W(3)=acc107bd.
namely ( 3 c 57 90 a c a 1 f 0 2 e c 1 0 b 19 13 07 21 16 80 b d ) \begin{pmatrix} 3c & 57 & 90 & ac\\ a1 & f0 & 2e & c1\\ 0b & 19 & 13 & 07\\ 21 & 16 & 80 & bd \end{pmatrix} ⎝⎜⎜⎛3ca10b2157f01916902e1380acc107bd⎠⎟⎟⎞ The next sub key segment is W ( 4 ) W(4) W(4), because 4 yes 4 Multiple , therefore W ( 4 ) = W ( 0 ) X O R T [ W ( 3 ) ] W(4)=W(0) \quad XOR \quad T[W(3)] W(4)=W(0)XORT[W(3)] T [ W ( 3 ) ] T[W(3)] T[W(3)] The calculation steps are as follows :
(1) Circulate W ( 3 ) W(3) W(3) Element shift : a c c 107 b d acc107bd acc107bd Turned into c 107 b d a c c107bdac c107bdac.
(2) take c 107 b d a c c107bdac c107bdac As S- Box input , Output 78857 a 91 78857a91 78857a91.
(3) Calculate a round of constants r ( 4 ) = 2 0 = 01 r(4)=2^0=01 r(4)=20=01( In hexadecimal ).
(4) take r ( 4 ) r(4) r(4) And the first byte 78 Conduct XOR Logical operations : 78 X O R 01 = 79 78\quad XOR \quad 01=79 78XOR01=79.
therefore , T [ W ( 3 ) ] = 79857 a 91 T[W(3)]=79857a91 T[W(3)]=79857a91, also W ( 4 ) = 3 c a 10 b 21 X O R 79857 a 91 = 456471 b 0 W(4)=3ca10b21\quad XOR \quad 79857a91=456471b0 W(4)=3ca10b21XOR79857a91=456471b0
The rest 3 The sub key segment is calculated as follows : W ( 5 ) = W ( 1 ) X O R W ( 4 ) = 57 f 01916 X O R 456471 b 0 = 129468 a 6 ; W(5)=W(1) \quad XOR \quad W(4)=57f01916\quad XOR \quad 456471b0=129468a6; W(5)=W(1)XORW(4)=57f01916XOR456471b0=129468a6; W ( 6 ) = W ( 2 ) X O R W ( 5 ) = 902 c 1380 X O R 129468 a 6 = 82 b 87 b 26 ; W(6)=W(2) \quad XOR \quad W(5)=902c1380 \quad XOR \quad 129468a6=82b87b26; W(6)=W(2)XORW(5)=902c1380XOR129468a6=82b87b26; W ( 7 ) = W ( 3 ) X O R W ( 6 ) = a c c 107 b d X O R 82 b 87 b 26 = 2 e 797 c 9 b ; W(7)=W(3) \quad XOR \quad W(6)=acc107bd \quad XOR \quad 82b87b26=2e797c9b; W(7)=W(3)XORW(6)=acc107bdXOR82b87b26=2e797c9b;
therefore , The key for the first round is : 456471 b 0 129468 a 6 82 b 87 b 26 2 e 797 c 9 b 456471b0\quad129468a6\quad82b87b26\quad2e797c9b 456471b0129468a682b87b262e797c9b.
AES The key generation code is as follows :
// Constant in loop r Value
const unsigned char R[10] = {
0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1B,0x36};
// Key generation process
void CipherKeyExtended(unsigned char cipherKey[][4] , unsigned char cipherKeySum[][44])
{
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
cipherKeySum[i][j] = cipherKey[i][j];
}
}
unsigned char tempColumnLast[4] = {
0};
for(int j=4;j<44;j++)
{
if(j%4!=0)
{
for(int i=0;i<4;i++)
{
cipherKeySum[i][j] = cipherKeySum[i][j-4]^cipherKeySum[i][j-1];
}
}
else
{
for(int i=0;i<4;i++)
{
tempColumnLast[i] = cipherKeySum[i][j-1];
}
unsigned char temp = tempColumnLast[0];
for(int k=0;k<3;k++)
{
tempColumnLast[k] = tempColumnLast[k+1];
}
tempColumnLast[3] = temp;
for(int k=0;k<4;k++)
{
tempColumnLast[k] = SBox[(tempColumnLast[k]&0xF0)>>4][tempColumnLast[k]&0x0F];
}
tempColumnLast[0] = tempColumnLast[0]^R[j/4-1];
for(int i=0;i<4;i++)
{
cipherKeySum[i][j] = cipherKeySum[i][j-4]^tempColumnLast[i];
}
}
}
}
4.AES Decryption operation
4.1 Retrograde displacement
The row shift operation is column 4 A row spirals to the left , Then the reverse shift operation is the column 4 Rows spiral right , That is, the first line moves to the right 0 Bytes , The second line moves to the right 1 Bytes , The third line moves to the right 2 Bytes , The fourth line moves to the right 3 Bytes , As shown in the figure below .
example : Suppose there is a matrix that is : ( 1 d d c d 4 07 18 43 22 2 b f 6 40 10 25 65 47 2 f a f ) \begin{pmatrix} 1d & dc & d4 & 07\\ 18 & 43 & 22 & 2b\\ f6 & 40 & 10 & 25\\ 65 & 47 & 2f & af \end{pmatrix} ⎝⎜⎜⎛1d18f665dc434047d422102f072b25af⎠⎟⎟⎞ Perform a reverse shift operation on it , Then we get the matrix : ( 1 d d c d 4 07 2 b 18 43 22 10 25 f 6 40 47 2 f a f 65 ) \begin{pmatrix} 1d & dc & d4 & 07\\ 2b & 18 & 43 & 22\\ 10 & 25 & f6 & 40\\ 47 & 2f & af & 65 \end{pmatrix} ⎝⎜⎜⎛1d2b1047dc18252fd443f6af07224065⎠⎟⎟⎞
The code for the reverse shift operation is as follows :
void ReShiftRows(unsigned char inputTextEncrypt [][4])
{
unsigned char temp = 0;
for(int i=1;i<4;i++)
{
for(int j=0;j<i;j++)
{
temp = inputTextEncrypt[i][3];
inputTextEncrypt[i][3] = inputTextEncrypt[i][2];
inputTextEncrypt[i][2] = inputTextEncrypt[i][1];
inputTextEncrypt[i][1] = inputTextEncrypt[i][0];
inputTextEncrypt[i][0] = temp;
}
}
}
4.2 The inverse S- Box replacement
The inverse S- Box replacement S- The box is also a 16 × 16 16\times16 16×16 Matrix , As shown in the following code . Each element of the column is used as input to specify S- The address of the box : front 4 Bit specifies S- The line of the box , after 4 Bit specifies S- Columns of boxes . Determined by rows and columns S- The element of the box position replaces the element of the corresponding position in the ciphertext matrix .
// The inverse S box
const unsigned char ReSBox[16][16] = {
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
{
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb},
{
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb},
{
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e},
{
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25},
{
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92},
{
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84},
{
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06},
{
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b},
{
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73},
{
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e},
{
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b},
{
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4},
{
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f},
{
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef},
{
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61},
{
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d}
};
example : Suppose the ciphertext matrix is : ( 2 c 50 b 7 92 a 8 a 8 e f 45 a a a 8 92 f 9 b 7 7 f b 7 8 f ) \begin{pmatrix} 2c & 50 & b7 & 92\\ a8 & a8 & ef & 45\\ aa & a8 & 92 & f9\\ b7 & 7f & b7 & 8f \end{pmatrix} ⎝⎜⎜⎛2ca8aab750a8a87fb7ef92b79245f98f⎠⎟⎟⎞ Through inversion S- After the box replacement operation , The matrix becomes : ( 42 6 c 20 74 6 f 6 f 61 68 62 6 f 74 69 20 6 b 20 73 ) \begin{pmatrix} 42& 6c & 20 & 74\\ 6f& 6f & 61 & 68\\ 62& 6f & 74 & 69\\ 20& 6b & 20 & 73 \end{pmatrix} ⎝⎜⎜⎛426f62206c6f6f6b2061742074686973⎠⎟⎟⎞
The inverse S- The code for the box replacement operation is as follows :
void ReSBoxFunc(unsigned char inputText[][4],unsigned char inputTextEncrypt[][4])
{
unsigned int row=0,column=0;
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
row = (inputText[i][j] & 0xF0) >> 4;
column = inputText[i][j]&0x0F;
inputTextEncrypt[i][j] = ReSBox[row][column];
}
}
}
4.3 Key adding operation
The key encryption operation performed during decryption is the same as that used during encryption , Note that the same round key is used for encryption and decryption .
4.4 Reverse column mixing operation
The inverse column mixing operation is realized by matrix multiplication . Compare the ciphertext matrix with the fixed matrix ( In hexadecimal ) Multiply , As shown below . ( c 0 c 1 c 2 c 3 ) = ( 0 E 0 B 0 D 09 09 0 E 0 B 0 D 0 D 09 0 E 0 B 0 B 0 D 09 0 E ) ( b 0 b 1 b 2 b 3 ) \begin{pmatrix} c_0 \\ c_1 \\ c_2 \\ c_3 \end{pmatrix} = \begin{pmatrix} 0E & 0B & 0D & 09\\ 09 & 0E & 0B & 0D\\ 0D & 09 & 0E & 0B\\ 0B & 0D & 09 & 0E \end{pmatrix} \begin{pmatrix} b_0 \\ b_1 \\ b_2 \\ b_3 \end{pmatrix} ⎝⎜⎜⎛c0c1c2c3⎠⎟⎟⎞=⎝⎜⎜⎛0E090D0B0B0E090D0D0B0E09090D0B0E⎠⎟⎟⎞⎝⎜⎜⎛b0b1b2b3⎠⎟⎟⎞ Here's how to multiply .
Suppose there is a byte B B B, Then there are :
B × ′ 0 9 ′ = B × ( ′ 0 8 ′ ⊕ ′ 0 1 ′ ) = ( B × ′ 0 2 ′ × ′ 0 2 ′ × ′ 0 2 ′ ) ⊕ ( B × ′ 0 1 ′ ) ; B × ′ 0 B ′ = B × ( ′ 0 8 ′ ⊕ ′ 0 2 ′ ⊕ ′ 0 1 ′ ) = ( B × ′ 0 2 ′ × ′ 0 2 ′ × ′ 0 2 ′ ) ⊕ ( B × ′ 0 2 ′ ) ⊕ ( B × ′ 0 1 ′ ) ; B × ′ 0 D ′ = B × ( ′ 0 8 ′ ⊕ ′ 0 4 ′ ⊕ ′ 0 1 ′ ) = ( B × ′ 0 2 ′ × ′ 0 2 ′ × ′ 0 2 ′ ) ⊕ ( B × ′ 0 2 ′ × ′ 0 2 ′ ) ⊕ ( B × ′ 0 1 ′ ) ; B × ′ 0 E ′ = B × ( ′ 0 8 ′ ⊕ ′ 0 4 ′ ⊕ ′ 0 2 ′ ) = ( B × ′ 0 2 ′ × ′ 0 2 ′ × ′ 0 2 ′ ) ⊕ ( B × ′ 0 2 ′ × ′ 0 2 ′ ) ⊕ ( B × ′ 0 2 ′ ) ; B\times '09'=B\times ('08'\oplus '01')=(B\times'02'\times '02'\times '02')\oplus (B\times '01');\\ B\times '0B'=B\times ('08'\oplus '02'\oplus '01')=(B\times'02'\times '02'\times '02')\oplus (B\times'02')\oplus (B\times '01');\\ B\times '0D'=B\times ('08'\oplus '04'\oplus '01')=(B\times'02'\times '02'\times '02')\oplus (B\times'02'\times '02')\oplus (B\times '01');\\ B\times '0E'=B\times ('08'\oplus '04'\oplus '02')=(B\times'02'\times '02'\times '02')\oplus (B\times'02'\times '02')\oplus (B\times '02');\\ B×′09′=B×(′08′⊕′01′)=(B×′02′×′02′×′02′)⊕(B×′01′);B×′0B′=B×(′08′⊕′02′⊕′01′)=(B×′02′×′02′×′02′)⊕(B×′02′)⊕(B×′01′);B×′0D′=B×(′08′⊕′04′⊕′01′)=(B×′02′×′02′×′02′)⊕(B×′02′×′02′)⊕(B×′01′);B×′0E′=B×(′08′⊕′04′⊕′02′)=(B×′02′×′02′×′02′)⊕(B×′02′×′02′)⊕(B×′02′);
example : Suppose the ciphertext matrix is : ( 60 65 67 63 79 e 7 f 9 00 46 a 3 7 e 52 74 c c 13 98 ) \begin{pmatrix} 60 & 65 & 67 & 63\\ 79 & e7 & f9 & 00\\ 46 & a3 & 7e & 52\\ 74 & cc & 13 & 98 \end{pmatrix} ⎝⎜⎜⎛6079467465e7a3cc67f97e1363005298⎠⎟⎟⎞ After the reverse column mixing operation , have to : ( a 2 8 b 0 e f 7 5 b 07 43 64 d 2 8 c e a 8 f 00 e d 54 b 5 ) = ( 0 E 0 B 0 D 09 09 0 E 0 B 0 D 0 D 09 0 E 0 B 0 B 0 D 09 0 E ) ( 60 65 67 63 79 e 7 f 9 00 46 a 3 7 e 52 74 c c 13 98 ) \begin{pmatrix} a2 & 8b & 0e & f7\\ 5b & 07 & 43 & 64\\ d2 & 8c & ea & 8f\\ 00 & ed & 54 & b5 \end{pmatrix} = \begin{pmatrix} 0E & 0B & 0D & 09\\ 09 & 0E & 0B & 0D\\ 0D & 09 & 0E & 0B\\ 0B & 0D & 09 & 0E \end{pmatrix} \begin{pmatrix} 60 & 65 & 67 & 63\\ 79 & e7 & f9 & 00\\ 46 & a3 & 7e & 52\\ 74 & cc & 13 & 98 \end{pmatrix} ⎝⎜⎜⎛a25bd2008b078ced0e43ea54f7648fb5⎠⎟⎟⎞=⎝⎜⎜⎛0E090D0B0B0E090D0D0B0E09090D0B0E⎠⎟⎟⎞⎝⎜⎜⎛6079467465e7a3cc67f97e1363005298⎠⎟⎟⎞ Following calculation : ( 0 E 0 B 0 D 09 ) ( 60 79 46 74 ) \begin{pmatrix} 0E & 0B & 0D & 09 \end{pmatrix} \begin{pmatrix} 60 \\ 79 \\ 46 \\ 74 \end{pmatrix} (0E0B0D09)⎝⎜⎜⎛60794674⎠⎟⎟⎞
60 × ′ 0 E ′ = ( 01100000 × ′ 0 2 ′ × ′ 0 2 ′ × ′ 0 2 ′ ) ⊕ ( 01100000 × ′ 0 2 ′ × ′ 0 2 ′ ) ⊕ ( 01100000 × ′ 0 2 ′ ) = ( 11000000 × ′ 0 2 ′ × ′ 0 2 ′ ) ⊕ ( 11000000 × ′ 0 2 ′ ) ⊕ ( 11000000 ) = ( 10011011 × ′ 0 2 ′ ) ⊕ ( 10011011 ) ⊕ ( 11000000 ) = ( 00101101 ) ⊕ ( 10011011 ) ⊕ ( 11000000 ) = 01110110 60\times '0E'=(01100000\times '02'\times '02'\times '02')\oplus (01100000\times '02'\times '02')\oplus(01100000\times '02')\\ =(11000000\times '02'\times '02')\oplus (11000000\times '02') \oplus (11000000)\\ =(10011011\times '02')\oplus (10011011)\oplus (11000000)\\ =(00101101)\oplus (10011011)\oplus (11000000)=01110110 60×′0E′=(01100000×′02′×′02′×′02′)⊕(01100000×′02′×′02′)⊕(01100000×′02′)=(11000000×′02′×′02′)⊕(11000000×′02′)⊕(11000000)=(10011011×′02′)⊕(10011011)⊕(11000000)=(00101101)⊕(10011011)⊕(11000000)=01110110
79 × ′ 0 B ′ = ( 01111001 × ′ 0 2 ′ × ′ 0 2 ′ × ′ 0 2 ′ ) ⊕ ( 01111001 × ′ 0 2 ′ ) ⊕ ( 01111001 × ′ 0 1 ′ ) = ( 11110010 × ′ 0 2 ′ × ′ 0 2 ′ ) ⊕ ( 11110010 ) ⊕ ( 01111001 ) = ( 11111111 × ′ 0 2 ′ ) ⊕ ( 11110010 ) ⊕ ( 01111001 ) = ( 11100101 ) ⊕ ( 11110010 ) ⊕ ( 01111001 ) = 01101110 79\times '0B'=(01111001\times '02'\times '02'\times '02')\oplus (01111001\times '02')\oplus (01111001\times '01')\\ =(11110010\times '02'\times '02')\oplus (11110010)\oplus (01111001)\\ =(11111111\times '02')\oplus (11110010)\oplus (01111001)\\ =(11100101)\oplus (11110010)\oplus (01111001)=01101110 79×′0B′=(01111001×′02′×′02′×′02′)⊕(01111001×′02′)⊕(01111001×′01′)=(11110010×′02′×′02′)⊕(11110010)⊕(01111001)=(11111111×′02′)⊕(11110010)⊕(01111001)=(11100101)⊕(11110010)⊕(01111001)=01101110
46 × ′ 0 D ′ = ( 01000110 × ′ 0 2 ′ × ′ 0 2 ′ × ′ 0 2 ′ ) ⊕ ( 01000110 × ′ 0 2 ′ × ′ 0 2 ′ ) ⊕ ( 01000110 × ′ 0 1 ′ ) = ( 10001100 × ′ 0 2 ′ × ′ 0 2 ′ ) ⊕ ( 10001100 × ′ 0 2 ′ ) ⊕ ( 01000110 ) = ( 00000011 × ′ 0 2 ′ ) ⊕ ( 00000011 ) ⊕ ( 01000110 ) = ( 00000110 ) ⊕ ( 00000011 ) ⊕ ( 01000110 ) = 01000011 46\times '0D'=(01000110\times '02'\times '02'\times '02')\oplus (01000110\times '02'\times '02')\oplus (01000110\times '01')\\ =(10001100\times '02'\times '02')\oplus(10001100\times '02')\oplus (01000110)\\ =(00000011\times '02')\oplus (00000011)\oplus (01000110)\\ =(00000110)\oplus (00000011)\oplus (01000110)=01000011 46×′0D′=(01000110×′02′×′02′×′02′)⊕(01000110×′02′×′02′)⊕(01000110×′01′)=(10001100×′02′×′02′)⊕(10001100×′02′)⊕(01000110)=(00000011×′02′)⊕(00000011)⊕(01000110)=(00000110)⊕(00000011)⊕(01000110)=01000011
74 × ′ 0 9 ′ = ( 01110100 × ′ 0 2 ′ × ′ 0 2 ′ × ′ 0 2 ′ ) ⊕ ( 01110100 × ′ 0 1 ′ ) = ( 11101000 × ′ 0 2 ′ ) ⊕ ( 01110100 ) = ( 11001011 × ′ 0 2 ′ ) ⊕ ( 01110100 ) = ( 10001101 ) ⊕ ( 01110100 ) = 11111001 74\times '09'=(01110100\times '02'\times '02'\times '02')\oplus (01110100\times '01')\\ =(11101000\times '02')\oplus (01110100)\\ =(11001011\times '02')\oplus (01110100)\\ =(10001101)\oplus (01110100)=11111001 74×′09′=(01110100×′02′×′02′×′02′)⊕(01110100×′01′)=(11101000×′02′)⊕(01110100)=(11001011×′02′)⊕(01110100)=(10001101)⊕(01110100)=11111001
01110110 ⊕ 01101110 ⊕ 01000011 ⊕ 11111001 = 10100010 = a 2 01110110\oplus01101110\oplus01000011\oplus11111001=10100010=a2 01110110⊕01101110⊕01000011⊕11111001=10100010=a2
The code for inverse column mixing is as follows :
unsigned char GFMul04(unsigned char num)
{
unsigned char temp=num;
for(int i=0;i<2;i++)
{
temp = GFMul02(temp);
}
return temp;
}
unsigned char GFMul08(unsigned char num)
{
unsigned char temp=num;
for(int i=0;i<3;i++)
{
temp = GFMul02(temp);
}
return temp;
}
unsigned char GFMul09(unsigned char num)
{
return GFMul08(num)^GFMul01(num);
}
unsigned char GFMul0B(unsigned char num)
{
return GFMul08(num)^GFMul02(num)^GFMul01(num);
}
unsigned char GFMul0D(unsigned char num)
{
return GFMul08(num)^GFMul04(num)^GFMul01(num);
}
unsigned char GFMul0E(unsigned char num)
{
return GFMul08(num)^GFMul04(num)^GFMul02(num);
}
unsigned char ReGFMulAll(unsigned char num1,unsigned char num2)
{
if(num2==0x09)
return GFMul09(num1);
else if(num2==0x0B)
return GFMul0B(num1);
else if(num2==0x0D)
return GFMul0D(num1);
else if(num2==0x0E)
return GFMul0E(num1);
}
void ReColumnMix(unsigned char inputTextColumnMix [][4],unsigned char inputTextEncrypt [][4])
{
for(int j=0;j<4;j++)
{
for(int i=0;i<4;i++)
{
inputTextEncrypt[i][j] = ReGFMulAll(inputTextColumnMix[0][j],ReGFMatrix[i][0])^ReGFMulAll(inputTextColumnMix[1][j],ReGFMatrix[i][1])^ReGFMulAll(inputTextColumnMix[2][j],ReGFMatrix[i][2])^ReGFMulAll(inputTextColumnMix[3][j],ReGFMatrix[i][3]);
}
}
}
5. Complete code
//aes.h
#ifndef _AES_H_
#define _AES_H_
#include<stdio.h>
//S box
const unsigned char SBox[16][16] ={
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
/*0*/{
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76 },
/*1*/{
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0 },
/*2*/{
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15 },
/*3*/{
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75 },
/*4*/{
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84 },
/*5*/{
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf },
/*6*/{
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8 },
/*7*/{
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2 },
/*8*/{
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73 },
/*9*/{
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb },
/*a*/{
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79 },
/*b*/{
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08 },
/*c*/{
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a },
/*d*/{
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e },
/*e*/{
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf },
/*f*/{
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }
};
// The inverse S box
const unsigned char ReSBox[16][16] = {
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
{
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb},
{
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb},
{
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e},
{
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25},
{
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92},
{
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84},
{
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06},
{
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b},
{
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73},
{
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e},
{
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b},
{
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4},
{
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f},
{
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef},
{
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61},
{
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d}
};
const unsigned char GFMatrix[4][4] = {
{
0x02,0x03,0x01,0x01},
{
0x01,0x02,0x03,0x01},
{
0x01,0x01,0x02,0x03},
{
0x03,0x01,0x01,0x02}
};
const unsigned char ReGFMatrix[4][4] = {
{
0x0E,0x0B,0x0D,0x09},
{
0x09,0x0E,0x0B,0x0D},
{
0x0D,0x09,0x0E,0x0B},
{
0x0B,0x0D,0x09,0x0E}
};
const unsigned char R[10] = {
0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1B,0x36};
#endif
#include "aes.h"
//S Box of replacement
void SBoxFunc(unsigned char inputText[][4], unsigned char inputTextEncrypt[][4]);
//S Box inverse permutation
void ReSBoxFunc(unsigned char inputText[][4],unsigned char inputTextEncrypt[][4]);
// Line shift
void ShiftRows(unsigned char inputTextEncrypt [][4]);
// Retrograde displacement
void ReShiftRows(unsigned char inputTextEncrypt [][4]);
// Column hybrid
unsigned char GFMul01(unsigned char num);
unsigned char GFMul02(unsigned char num);
unsigned char GFMul03(unsigned char num);
unsigned char GFMulAll(unsigned char num1,unsigned char num2);
void ColumnMix(unsigned char inputTextEncrypt [][4],unsigned char inputTextColumnMix [][4]);
// Inverse column mixing
unsigned char GFMul04(unsigned char num);
unsigned char GFMul08(unsigned char num);
unsigned char GFMul09(unsigned char num);
unsigned char GFMul0B(unsigned char num);
unsigned char GFMul0D(unsigned char num);
unsigned char GFMul0E(unsigned char num);
unsigned char ReGFMulAll(unsigned char num1,unsigned char num2);
void ReColumnMix(unsigned char inputTextColumnMix [][4],unsigned char inputTextEncrypt [][4]);
// Round key XOR
void RoundKeyXOR(unsigned char inputTextColumnMix [][4],unsigned char RoundKey [][4],unsigned char inputText[][4]);
// The key to expand
void CipherKeyExtended(unsigned char cipherKey[][4] , unsigned char cipherKeySum[][44]);
// encryption
void Encrypt(unsigned char inputText[][4],unsigned char cipherKeySum[][44]);
// Decrypt
void Decrypt(unsigned char inputText[][4],unsigned char cipherKeySum[][44]);
// Yes 4*4 Matrix for printing
void printMatrix(unsigned char matrix[][4]);
void printMatrix(unsigned char matrix[][4])
{
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
printf("%.2x ",matrix[i][j]);
}
printf("\n");
}
}
void SBoxFunc(unsigned char inputText[][4], unsigned char inputTextEncrypt[][4])
{
unsigned int row=0,column=0;
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
row = (inputText[i][j] & 0xF0) >> 4;
column = inputText[i][j]&0x0F;
inputTextEncrypt[i][j] = SBox[row][column];
}
}
}
void ReSBoxFunc(unsigned char inputText[][4],unsigned char inputTextEncrypt[][4])
{
unsigned int row=0,column=0;
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
row = (inputText[i][j] & 0xF0) >> 4;
column = inputText[i][j]&0x0F;
inputTextEncrypt[i][j] = ReSBox[row][column];
}
}
}
void ShiftRows(unsigned char inputTextEncrypt [][4])
{
unsigned char temp = 0;
for(int i=1;i<4;i++)
{
for(int j=0;j<i;j++)
{
temp = inputTextEncrypt[i][0];
inputTextEncrypt[i][0] = inputTextEncrypt[i][1];
inputTextEncrypt[i][1] = inputTextEncrypt[i][2];
inputTextEncrypt[i][2] = inputTextEncrypt[i][3];
inputTextEncrypt[i][3] = temp;
}
}
}
void ReShiftRows(unsigned char inputTextEncrypt [][4])
{
unsigned char temp = 0;
for(int i=1;i<4;i++)
{
for(int j=0;j<i;j++)
{
temp = inputTextEncrypt[i][3];
inputTextEncrypt[i][3] = inputTextEncrypt[i][2];
inputTextEncrypt[i][2] = inputTextEncrypt[i][1];
inputTextEncrypt[i][1] = inputTextEncrypt[i][0];
inputTextEncrypt[i][0] = temp;
}
}
}
unsigned char GFMul01(unsigned char num)
{
return num;
}
unsigned char GFMul02(unsigned char num)
{
unsigned char temp = num>>7&0xFF;
if(temp==0x00)
return num<<1&0xFF;
else if(temp==0x01)
return (num<<1&0xFF)^0x1B;
}
unsigned char GFMul03(unsigned char num)
{
return GFMul01(num)^GFMul02(num);
}
unsigned char GFMulAll(unsigned char num1,unsigned char num2)
{
if(num2==0x01)
return GFMul01(num1);
else if(num2==0x02)
return GFMul02(num1);
else if(num2==0x03)
return GFMul03(num1);
}
void ColumnMix(unsigned char inputTextEncrypt [][4],unsigned char inputTextColumnMix [][4])
{
for(int j=0;j<4;j++)
{
for(int i=0;i<4;i++)
{
inputTextColumnMix[i][j] = GFMulAll(inputTextEncrypt[0][j],GFMatrix[i][0])^GFMulAll(inputTextEncrypt[1][j],GFMatrix[i][1])^GFMulAll(inputTextEncrypt[2][j],GFMatrix[i][2])^GFMulAll(inputTextEncrypt[3][j],GFMatrix[i][3]);
}
}
}
unsigned char GFMul04(unsigned char num)
{
unsigned char temp=num;
for(int i=0;i<2;i++)
{
temp = GFMul02(temp);
}
return temp;
}
unsigned char GFMul08(unsigned char num)
{
unsigned char temp=num;
for(int i=0;i<3;i++)
{
temp = GFMul02(temp);
}
return temp;
}
unsigned char GFMul09(unsigned char num)
{
return GFMul08(num)^GFMul01(num);
}
unsigned char GFMul0B(unsigned char num)
{
return GFMul08(num)^GFMul02(num)^GFMul01(num);
}
unsigned char GFMul0D(unsigned char num)
{
return GFMul08(num)^GFMul04(num)^GFMul01(num);
}
unsigned char GFMul0E(unsigned char num)
{
return GFMul08(num)^GFMul04(num)^GFMul02(num);
}
unsigned char ReGFMulAll(unsigned char num1,unsigned char num2)
{
if(num2==0x09)
return GFMul09(num1);
else if(num2==0x0B)
return GFMul0B(num1);
else if(num2==0x0D)
return GFMul0D(num1);
else if(num2==0x0E)
return GFMul0E(num1);
}
void ReColumnMix(unsigned char inputTextColumnMix [][4],unsigned char inputTextEncrypt [][4])
{
for(int j=0;j<4;j++)
{
for(int i=0;i<4;i++)
{
inputTextEncrypt[i][j] = ReGFMulAll(inputTextColumnMix[0][j],ReGFMatrix[i][0])^ReGFMulAll(inputTextColumnMix[1][j],ReGFMatrix[i][1])^ReGFMulAll(inputTextColumnMix[2][j],ReGFMatrix[i][2])^ReGFMulAll(inputTextColumnMix[3][j],ReGFMatrix[i][3]);
}
}
}
void RoundKeyXOR(unsigned char inputTextColumnMix [][4],unsigned char RoundKey [][4],unsigned char inputText[][4])
{
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
inputText[i][j] = inputTextColumnMix[i][j]^RoundKey[i][j];
}
}
}
void CipherKeyExtended(unsigned char cipherKey[][4] , unsigned char cipherKeySum[][44])
{
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
cipherKeySum[i][j] = cipherKey[i][j];
}
}
unsigned char tempColumnLast[4] = {
0};
for(int j=4;j<44;j++)
{
if(j%4!=0)
{
for(int i=0;i<4;i++)
{
cipherKeySum[i][j] = cipherKeySum[i][j-4]^cipherKeySum[i][j-1];
}
}
else
{
for(int i=0;i<4;i++)
{
tempColumnLast[i] = cipherKeySum[i][j-1];
}
unsigned char temp = tempColumnLast[0];
for(int k=0;k<3;k++)
{
tempColumnLast[k] = tempColumnLast[k+1];
}
tempColumnLast[3] = temp;
for(int k=0;k<4;k++)
{
tempColumnLast[k] = SBox[(tempColumnLast[k]&0xF0)>>4][tempColumnLast[k]&0x0F];
}
tempColumnLast[0] = tempColumnLast[0]^R[j/4-1];
for(int i=0;i<4;i++)
{
cipherKeySum[i][j] = cipherKeySum[i][j-4]^tempColumnLast[i];
}
}
}
}
void Encrypt(unsigned char inputText[][4],unsigned char cipherKeySum[][44])
{
unsigned char inputTextEncrypt[4][4] = {
0};
unsigned char inputTextColumnMix[4][4] = {
0};
unsigned char cipherKey[4][4] = {
0};
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
cipherKey[i][j] = cipherKeySum[i][j];
}
}
RoundKeyXOR(inputText,cipherKey,inputText);
for(int i=1;i<=9;i++)
{
for(int m=0;m<4;m++)
{
for(int n=0;n<4;n++)
{
cipherKey[m][n] = cipherKeySum[m][4*i+n];
}
}
SBoxFunc(inputText,inputTextEncrypt);
ShiftRows(inputTextEncrypt);
ColumnMix(inputTextEncrypt,inputTextColumnMix);
RoundKeyXOR(inputTextColumnMix,cipherKey,inputText);
}
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
cipherKey[i][j] = cipherKeySum[i][40+j];
}
}
SBoxFunc(inputText,inputTextEncrypt);
ShiftRows(inputTextEncrypt);
RoundKeyXOR(inputTextEncrypt,cipherKey,inputText);
}
void Decrypt(unsigned char inputText[][4],unsigned char cipherKeySum[][44])
{
unsigned char reInputTextEncrypt[4][4] = {
0};
unsigned char reInputTextRoundKeyXOR[4][4] = {
0};
unsigned char cipherKey[4][4] = {
0};
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
cipherKey[i][j] = cipherKeySum[i][40+j];
}
}
RoundKeyXOR(inputText,cipherKey,inputText);
for(int m=1;m<=9;m++)
{
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
cipherKey[i][j] = cipherKeySum[i][40-4*m+j];
}
}
ReShiftRows(inputText);
ReSBoxFunc(inputText,reInputTextEncrypt);
RoundKeyXOR(reInputTextEncrypt,cipherKey,reInputTextRoundKeyXOR);
ReColumnMix(reInputTextRoundKeyXOR,inputText);
}
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
cipherKey[i][j] = cipherKeySum[i][j];
}
}
ReSBoxFunc(inputText,reInputTextEncrypt);
ReShiftRows(reInputTextEncrypt);
RoundKeyXOR(reInputTextEncrypt,cipherKey,inputText);
}
int main()
{
unsigned char inputText1[4][4]={
{
0x42,0x6c,0x20,0x74},
{
0x6f,0x6f,0x61,0x68},
{
0x62,0x6f,0x74,0x69},
{
0x20,0x6b,0x20,0x73}};
unsigned char inputText2[4][4]={
{
0x1e,0xca,0xd6,0xce},
{
0x03,0xf8,0x98,0xfa},
{
0x40,0x7e,0x93,0x4d},
{
0xd2,0xc8,0x82,0xd1}};
unsigned char cipherKey[4][4] = {
{
0x3c,0x57,0x90,0xac},
{
0xa1,0xf0,0x2c,0xc1},
{
0x0b,0x19,0x13,0x07},
{
0x21,0x16,0x80,0xbd}
};
unsigned char cipherKeySum[4][44] = {
0};
CipherKeyExtended(cipherKey,cipherKeySum);
printf("***********AES Encryption and decryption operation ***********\n The plaintext to be encrypted is :\n");
printMatrix(inputText1);
printf("\n The ciphertext to be decrypted is :\n");
printMatrix(inputText2);
printf("\n The key is extended to :\n");
for(int i=0;i<4;i++)
{
for(int j=0;j<44;j++)
{
printf("%.2x ",cipherKeySum[i][j]);
}
printf("\n");
}
printf("\n===============================================================================================\n\n");
Encrypt(inputText1,cipherKeySum);
Decrypt(inputText2,cipherKeySum);
printf(" The result after encryption is :\n");
printMatrix(inputText1);
printf("\n The decrypted result is :\n");
printMatrix(inputText2);
return 0;
}
The running results are as follows :
Welcome to comment and collect !!!
边栏推荐
- Boxing and UnBoxing
- c#线程间操作无效,去掉这个检查的
- Diode, triode
- Genesis public chain is determined to appear at the consensus 2022 Conference
- 目前技术圈最全面的 Layer2 研究总结
- Research Report on market supply and demand and strategy of aquaculture vaccine industry in China
- 漏洞复现_CVE-2020-0796 永恒之黑漏洞_遇坑_已解决
- Ayutthaya, Bangkok, Thailand, was rated as "the most worthwhile city to visit in the post epidemic era" by Forbes
- 世界海洋日 | 徜徉于新泽西海洋生物水族馆,记录趣味纽约旅行
- Redis数据类型之list和set以及sorted_set排序
猜你喜欢

跳过51单片机,直接学STM32有什么严重后果
![OS Experiment 7 [document management]](/img/9a/348cae236657fd016436150a1fc3b2.png)
OS Experiment 7 [document management]

大佬们,帮帮我吧!重装MySQL,到设置密码就出现current root password
![[homeassistant shakes hands with 28byj-48 stepping motor]](/img/ed/c71b9e83df4b60d395e30cb969d05a.png)
[homeassistant shakes hands with 28byj-48 stepping motor]

Introduction to redis - understanding and downloading

Sum of redis data types hash

【Lingo】运算符

The latest Jilin construction safety officer simulation question bank and answers in 2022

Using wechat games to achieve Dragon Boat battle - making zongzi

Web 3: a new era of Internet development
随机推荐
Qt5.9.5+Jetson Nano开发:unknown module(s) in qt designer
Sum of redis data types hash
3775 array completion (ring diagram)
idea jdbc报错
What does tops/w mean
SqlServer还原失败(数据库正在使用,无法获得对数据库的独占访问权)
Research Report on aquatic feed granulator industry - market status analysis and development prospect forecast
Ayutthaya, Bangkok, Thailand, was rated as "the most worthwhile city to visit in the post epidemic era" by Forbes
Renewable energy consulting 2022 Global Industry Analysis Report
Web page test of software test
嵌入式还有人关注吗?嵌入式测试需要关注哪些问题?
Research Report on market supply and demand and strategy of Chinese water jet cutting machine (water jet cutting machine) industry
泰国曼谷大城府被福布斯评为“后疫情时代最值得一去的城市”
List, set and sorted of redis data types_ Set sort
什么是单元测试,为什么要做单元测试
How to conduct interface test and how to do interface test well
業務系統該如何防病毒
功能测试包含哪些测试?分别有什么作用?
Global industry analysis report of spray drying machinery in 2022
Global industry analysis report of food dehydrators in 2022






