当前位置:网站首页>[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 structure

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 .
 Insert picture description here

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 .
 Insert picture description here

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=02010103030201010103020101010302b0b1b2b4
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=020101030302010101030201010103022ca8928f50eff9b7b745aa7f92a8a8b7
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=0101100000000000=01011000;03×a8=02×a8(10101000)01×a8(10101000)=010100000001101110101000=11100011;01×92=10010010;01×8f=10001111;01011000111000111001001010001111=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 .
 Insert picture description here

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} a645314bc43294936fa73cd3c38db3d8XOR01e1cc59a3447306902004301211a9b4=a7a4fd126776e795ff8738e3d19c1a6c
a 6 ⊕ 01 = a 7 ; c 4 ⊕ a 3 = 67 ; a6\oplus01=a7;c4\oplus a3=67; a601=a7;c4a3=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(i4)XORW(i1) 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(i4)XORT[W(i1)] among T [ W ( i − 1 ) ] T[W(i-1)] T[W(i1)] yes W ( i − 1 ) W(i-1) W(i1) A form of transformation , It is implemented in the following way :
(1) Circulate W ( i − 1 ) W(i-1) W(i1) 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(i4)/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 :
 Insert picture description here

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 .
 Insert picture description here

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=0E090D0B0B0E090D0D0B0E09090D0B0Eb0b1b2b3 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×(0801)=(B×02×02×02)(B×01);B×0B=B×(080201)=(B×02×02×02)(B×02)(B×01);B×0D=B×(080401)=(B×02×02×02)(B×02×02)(B×01);B×0E=B×(080402)=(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=0E090D0B0B0E090D0D0B0E09090D0B0E6079467465e7a3cc67f97e1363005298 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 01110110011011100100001111111001=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 :
 Insert picture description here

Welcome to comment and collect !!!

原网站

版权声明
本文为[Xiaoyuan Xiaoyuan eats dumplings]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/161/202206100823094801.html