AES
AES
The Advanced Encryption Standard
On October 2, 2000, Rijndael was selected to be the Advanced Encryption Standard
Mathematical Preliminaries
Finite Fields
All byte values in AES will be presented as the concatenation of its individual bit values(0 or 1) in order :
The bytess in AES are interpreted as finite field elements using a polynomial representation:
Addition
The addition of two elements in a finite field is achieved by adding the coefficients for the corresponding powers in the polynomials for the two elements.
The addition is performed with the XOR operation:
For two bytes :
1 + 1 mod 2 = 0
1 + 0 mod 2 = 1
0 + 1 mod 2 = 1
0 + 0 mod 2 = 0
1 - 1 mod 2 = 0
1 - 0 mod 2 = 1
0 - 1 mod 2 = 1
0 - 0 mod 2 = 0
Subtraction of polynomials is identical to addition of polynomials.
Multiplication
In the polynomial representation, multiplication in
A polynomial is irreducible if its only divisors are one and itself. For AES, this irreducible polynomial is
For any non-zero binary polynomial
The extended Euclidean algorithm is used to compute polynomials
Hence
Multiplication by x
-
is obtained by modulo-
: Done -
: modulo i.e. XOR
-
- a left shift
- a conditional bitwise XOR with
{1b}
This operation on bytes is denoted by xtime() , Multiplication by higher power of x can be implemented by repeated application of xtime()
一定要注意数字是十进制还是十六进制还是二进制!!!!
Polynimials with Coefficients in GF( )
**Four term polynomials can be defined with coefficients that are finite field elements : **
!!!! The coefficients here are finite field elements themselves, i.e. bytes, instead of bits
Addition
Addition is performed by adding the finite field coefficients of like power of x . This addition corresponds to an XOR operation between the corresponding bytes in each of the words.
Multiplication
-
is algebraically expanded, and like powers are collected : -
reduce
to modulo a polynomial of degree 4
description
参数
Parameters & Functions
-
K : Cipher key
-
Nb
: Number of columns (32-bit words) comprising the State. For AES, Nb = 4 -
Nk
: Number of 32-bit words comprising the Cipher Key. For AES, Nk = 4, 6, 8 -
Nr
: Number of rounds Nr = 10, 12, 14 -
Block length : 128
Block : Sequence of binary bits that comprise the input, output, State and Round Key. The length of a sequence is the number of bits it contains. Blocks are also interpreted as arrays of bytes.
-
Key length : 128, 192, 256 bits
-
: Nr = 10 if key length is 128 bits, Nr = 12 if key length is 192 bits, Nr = 14 if key length is 256 bits.
流程:
- Initialize State to be plaintext x , then perform ADD-ROUNDKEY (x-ors the RoundKey with State)
- For each of the first
rounds:- Perform a substitution operation : SUB-BYTES on State using a S-box.
- Perform a permutation SHIF-TROWS on State
- Perform a permutation MIX-COLUMNS on State
- Perform ADD-ROUNDKEY
- Perform SUB-TYPES, SHIFT-ROWS, ADD-ROUNDKEY
- Define the ciphertext y to be State
State(s 数组)
The State consists of four rows of bytes, each containing Nb bytes, where Nb is the block length divided by 32.
In the State array denoted by the symbol s, each individual byte has two indices(索引), with its row number r :
Hence, at the beginning of the Cipher or Inverse Cipher, the input array, in , is copied to the State array according to the scheme:
The four bytes in each column of the State array form 32-bit words, where the row number r provides an index for the four bytes within each word. The state can hence be interpreted as a one-dimensional array of 32 bit words:
Key Expansion
The Key Expansion generates a total of
The resulting key schedule consists of a linear array of 4-byte words, denoted
KeyExpansion(byte key[4*Nk], word x[Nb*(Nr+1)], Nk)
begin
word temp
i = 0
while(i < Nk)
w[i] = word(key[4*i], key[4*i+1], key[4*i+2], key[4*i+3])
i = i+1
end while
while(i < Nb * (Nr + 1))
temp = w[i-1]
if (i mod Nk == 0)
temp = SubWord(RotWord(temp)) xor Rcon[i/Nk]
else if (Nk > 6 and i mod Nk = 4)
temp = SubWord(temp)
end if
w[i] = w[i-Nk] xor temp
i = i + 1
end while
end
- The first Nk words of the expanded key are filled with the Cipher Key
- Following word : w[i]
- If :
, - else :
- If :
ROTWORD
SUBWORD
Apply the S-box to each of the four bytes :
where
RCon
an array of 10 words. Constants given by
代码实现
u8** KeyExpansion(u8* k) {
// Round Constant
u8** RCon = CalRoundConstant();
u8** w = (u8**)malloc(sizeof(u8*) * Nb * (Nr + 1));
for(int i = 0; i < 4; i++) {
w[i] = (u8*)malloc(sizeof(u8) * 4);
}
int i = 0;
u8* tmp;
// w[i] = word(key[4*i], key[4*i+1], key[4*i+2], key[4*i+3]), i < Nk
for(; i < Nk; i++) {
for(int j = 0; j < 4; j++) {
w[i][j] = k[i + 4 * j];
}
}
while(i < Nb * (Nr + 1)) {
tmp = Byte2Word(w, i - 1);
if(!(i % Nk)) {
// temp = SubWord(RotWord(temp)) xor Rcon[i/Nk]
RotWord(tmp);
SubWord(tmp);
for(int j = 0; j < 4; j++) {
tmp[j] = GFAdd(tmp[j], RCon[j][i/Nk]) ;
}
} else if ((Nk > 6) && (i % Nk == 4)){
SubWord(tmp);
}
// w[i] = w[i-Nk] xor temp
for(int j = 0; j < 4 ; j++) {
w[j][i] = w[j][i - Nk] ^ tmp[j];
}
i++;
}
return w;
}
cipher
流程分析
Cipher(byte in[4*Nb], type out[4*Nb], word w[Nb*(Nr + 1)]) // w[] contains the key schedule
begin
byte state[4][Nb]
state = in
AddRoundKey(state, w[0, Nb - 1])
for round = 1 step 1 to Nr - 1
SubBytes(state) // substitute bytes
ShiftRows(state)
MixColumns(state)
AddRoundKey(state, w[round*Nb, (round+1)*Nb - 1])
end for
SubBytes(state)
ShiftRows(state)
AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1])
out = state
end
SubBytes
Non-linear byte substitution that operates independently on each byte of the State using a substitution table(S-box) , which is a permutation of
In contrast to the S-boxes in DES, which are apparently "random" substitutions, the AES S-box can be defined algebraically.
the permutation
-
Take the multiplicative inverse in the finite field
( 把字节看做有限域 上的元素) -
Affine transformation(over
):

伪代码:
SUBTYPES(
) external
FIELDINV
,BINARYTOFIELD
,FIELDTOBINARY
if
then
/// All subscripts are to be reduced modulo 8 in the following loop
for
: DO
return
由于对每个已知输入,经过 S 盒的输出都是固定的,可以直接将 S 盒写成替代表的形式来减少计算开销。
代码实现
void SubBytes(u8** a) {
for(int j = 0; j < Nb; j++) {
for(int i = 0; i < 4; i++) {
a[i][j] = s_box[a[i][j] >> 4][a[i][j] & 0x0f];
}
}
}
ShiftRows()
代码实现
void ShiftRows(u8** a) {
u8* tmp = (u8*)malloc(sizeof(u8)* Nb);
for(int i = 1; i < 4; i++) {
for(int j = 0; j < Nb; j++) {
tmp[j] = a[i][j];
}
for(int j = 0; j < Nb; j++) {
a[i][j] = tmp[(j + i) % Nb];
}
}
free(tmp);
}
MixColumns()
MixColumns
operates in the State column-by-column, treating each column as a four-term polynomial over


乘法操作可以通过 x 乘实现
代码实现:
void MixColumns(u8** a) {
u8 tmp[4];
for(int j = 0; j < Nb; j++) {
tmp[0] = a[0][j];
tmp[1] = a[1][j];
tmp[2] = a[2][j];
tmp[3] = a[3][j];
a[0][j] = xtime(tmp[0]) ^ xtime(tmp[1]) ^ tmp[1] ^ tmp[2] ^ tmp[3];
a[1][j] = tmp[0] ^ xtime(tmp[1]) ^ xtime(tmp[2]) ^ tmp[2] ^ tmp[3];
a[2][j] = tmp[0] ^ tmp[1] ^ xtime(tmp[2]) ^ xtime(tmp[3]) ^ tmp[3];
a[3][j] = xtime(tmp[0]) ^ tmp[0] ^ tmp[1] ^ tmp[2] ^ xtime(tmp[3]);
}
}
AddRoundKey()


代码实现
u8* AddRoundKey(u8** state, u8** w, int round) {
for(int j = 0; j < Nb; j++){
for(int i = 0; i < 4; i++) {
state[i][j] = GFAdd(state[i][j], w[i][round * 4 + j]) ;
}
}
}
解密
直接反向解密
-
Inv_ShiftRows
: 反向右移 -
Inv_S-box
: S 先逆仿射变换再求逆 -
Inv_MixColumns
: 乘以矩阵的乘法逆元 -
AddRoundKey
: 逆变换即为自身
Pseudo Code
InvCipher(byte in[4*Nb], byte out[4*Nb], word w[Nb*(Nr+1)])
begin
byte state[4,Nb]
state = in
AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1])
for round = Nr-1 setp -1 to 1
InvShiftRows(state)
InvSubBytes(state)
AddRoundKey(state, w[round*Nb, (round+1)*Nb-1])
InvMixColumns(state)
end for
InvShiftRows(state)
InvSubBytes(state)
AddRoundKey(state, w[0, Nb-1])
out = state
end
完整代码:
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
#include<string.h>
#define u8 uint8_t
#define u32 uint32_t
const int Nb = 4; // 分组字块数
int Nr;
int Nk;
static u8 s_box[16][16] = {
// 0 1 2 3 4 5 6 7 8 9 a b c d e f
{0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76}, // 0
{0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0}, // 1
{0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15}, // 2
{0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75}, // 3
{0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84}, // 4
{0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf}, // 5
{0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8}, // 6
{0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2}, // 7
{0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73}, // 8
{0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb}, // 9
{0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79}, // a
{0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08}, // b
{0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a}, // c
{0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e}, // d
{0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf}, // e
{0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16}};// f
static u8 inv_s_box[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}, // 0
{0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb}, // 1
{0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e}, // 2
{0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25}, // 3
{0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92}, // 4
{0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84}, // 5
{0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06}, // 6
{0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b}, // 7
{0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73}, // 8
{0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e}, // 9
{0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b}, // a
{0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4}, // b
{0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f}, // c
{0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef}, // d
{0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61}, // e
{0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d}}; // f
u8 GFAdd(u8 a, u8 b) {
return a ^ b;
}
u8 GFSub(u8 a, u8 b) {
return a ^ b;
}
u8 xtime(u8 a) {
u8 msb = a & 0x80;
a = a << 1;
if(msb) {
return GFSub(a, 0x1b);
} else {
return a;
}
}
u8 GFMul(u8 a, u8 b) {
u8 ans = 0;
while(b) {
if(b & 0x1) {
ans = GFAdd(ans, a);
}
a = xtime(a);
b = b >> 1;
}
return ans;
}
void RotWord(u8* a) {
u8 tmp = a[0];
a[0] = a[1];
a[1] = a[2];
a[2] = a[3];
a[3] = tmp;
}
u8* Byte2Word(u8**a, int i) {
u8* b = (u8*)malloc(sizeof(u8) * 4);
b[0] = a[0][i];
b[1] = a[1][i];
b[2] = a[2][i];
b[3] = a[3][i];
return b;
}
void test_array(const char* str, u8** arr, int size) {
printf("%s: ", str);
for(int j = 0; j < size; j++) {
for(int i = 0; i < 4; i++) {
printf("%02x", arr[i][j]);
}
printf(" ");
}
printf("\n");
}
u8** CalRoundConstant() {
u8** RCon = (u8**)malloc(sizeof(u8*)* 11);
for(int i = 0; i < 11; i++) {
RCon[i] = (u8*)malloc(sizeof(u8)*4);
}
for(int i = 1; i < 4; i++) {
for(int j = 0; j < 11; j++) {
RCon[i][j] = 0;
}
}
RCon[0][1] = 0x01;
for(int i = 2; i <= 10; i++) {
RCon[0][i] = xtime(RCon[0][i - 1]);
}
// test_array("RCon", RCon, 11);
return RCon;
}
void ShiftRows(u8** a) {
u8* tmp = (u8*)malloc(sizeof(u8)* Nb);
for(int i = 1; i < 4; i++) {
for(int j = 0; j < Nb; j++) {
tmp[j] = a[i][j];
}
for(int j = 0; j < Nb; j++) {
a[i][j] = tmp[(j + i) % Nb];
}
}
free(tmp);
}
void InvShiftRows(u8** a) {
u8* tmp = (u8*)malloc(sizeof(u8)* Nb);
for(int i = 1; i < 4; i++) {
for(int j = 0; j < Nb; j++) {
tmp[j] = a[i][j];
}
for(int j = 0; j < Nb; j++) {
a[i][j] = tmp[(j - i + Nb) % Nb];
}
}
free(tmp);
}
void MixColumns(u8** a) {
u8 tmp[4];
for(int j = 0; j < Nb; j++) {
tmp[0] = a[0][j];
tmp[1] = a[1][j];
tmp[2] = a[2][j];
tmp[3] = a[3][j];
a[0][j] = GFMul(tmp[0], 0x02) ^ GFMul(tmp[1], 0x03) ^ GFMul(tmp[2], 0x01) ^GFMul(tmp[3], 0x01);
a[1][j] = GFMul(tmp[0], 0x01) ^ GFMul(tmp[1], 0x02) ^ GFMul(tmp[2], 0x03) ^GFMul(tmp[3], 0x01);
a[2][j] = GFMul(tmp[0], 0x01) ^ GFMul(tmp[1], 0x01) ^ GFMul(tmp[2], 0x02) ^GFMul(tmp[3], 0x03);
a[3][j] = GFMul(tmp[0], 0x03) ^ GFMul(tmp[1], 0x01) ^ GFMul(tmp[2], 0x01) ^GFMul(tmp[3], 0x02);
}
}
void InvMixColumns(u8** a) {
u8 tmp[4];
for(int j = 0; j < Nb; j++) {
tmp[0] = a[0][j];
tmp[1] = a[1][j];
tmp[2] = a[2][j];
tmp[3] = a[3][j];
a[0][j] = GFMul(tmp[0], 0x0e) ^ GFMul(tmp[1], 0x0b) ^ GFMul(tmp[2], 0x0d) ^GFMul(tmp[3], 0x09);
a[1][j] = GFMul(tmp[0], 0x09) ^ GFMul(tmp[1], 0x0e) ^ GFMul(tmp[2], 0x0b) ^GFMul(tmp[3], 0x0d);
a[2][j] = GFMul(tmp[0], 0x0d) ^ GFMul(tmp[1], 0x09) ^ GFMul(tmp[2], 0x0e) ^GFMul(tmp[3], 0x0b);
a[3][j] = GFMul(tmp[0], 0x0b) ^ GFMul(tmp[1], 0x0d) ^ GFMul(tmp[2], 0x09) ^GFMul(tmp[3], 0x0e);
}
}
u8* AddRoundKey(u8** state, u8** w, int round) {
for(int j = 0; j < Nb; j++){
for(int i = 0; i < 4; i++) {
state[i][j] = GFAdd(state[i][j], w[i][round * 4 + j]) ;
}
}
}
void SubBytes(u8** a) {
for(int j = 0; j < Nb; j++) {
for(int i = 0; i < 4; i++) {
a[i][j] = s_box[a[i][j] >> 4][a[i][j] & 0x0f];
}
}
}
void InvSubBytes(u8** a) {
for(int j = 0; j < Nb; j++) {
for(int i = 0; i < 4; i++) {
a[i][j] = inv_s_box[a[i][j] >> 4][a[i][j] & 0x0f];
}
}
}
void SubWord(u8* a) {
for(int i = 0; i < 4; i++) {
a[i] = s_box[a[i] >> 4][a[i] & 0x0f];
}
}
u8** KeyExpansion(u8* k) {
// Round Constant
u8** RCon = CalRoundConstant();
u8** w = (u8**)malloc(sizeof(u8*) * Nb * (Nr + 1));
for(int i = 0; i < 4; i++) {
w[i] = (u8*)malloc(sizeof(u8) * 4);
}
int j = 0;
u8* tmp;
// w[i] = word(key[4*i], key[4*i+1], key[4*i+2], key[4*i+3]), i < Nk
for(; j < Nk; j++) {
for(int i = 0; i < 4; i++) {
w[i][j] = k[i + 4 * j];
}
}
while(j < Nb * (Nr + 1)) {
tmp = Byte2Word(w, j - 1);
if(!(j % Nk)) {
// temp = SubWord(RotWord(temp)) xor Rcon[i/Nk]
RotWord(tmp);
SubWord(tmp);
for(int i = 0; i < 4; i++) {
tmp[i] = GFAdd(tmp[i], RCon[i][j/Nk]) ;
}
} else if ((Nk > 6) && (j % Nk == 4)){
SubWord(tmp);
}
// w[i] = w[i-Nk] xor temp
for(int i = 0; i < 4 ; i++) {
w[i][j] = w[i][j - Nk] ^ tmp[i];
}
j++;
}
return w;
}
u8** init(int key_size, u8* k, u8** state, u8* in) {
switch (key_size) { // 128/192/256bits
case 16: Nk = 4; Nr = 10; break;
case 24: Nk = 6; Nr = 12; break;
case 32: Nk = 8; Nr = 14; break;
}
u8** w = KeyExpansion(k);
for(int j = 0; j < Nb; j++) {
for(int i = 0; i < 4; i++) {
state[i][j] = in[i + 4 * j];
}
}
return w;
}
void AesEncrypt(int key_size, u8* k, u8* in, u8*out) {
u8** state = (u8**)malloc(sizeof(u8*) * Nb);
for(int i = 0; i < 4; i++) {
state[i] = (u8*)malloc(sizeof(u8) * 4);
}
u8** w = init(key_size, k, state, in);
AddRoundKey(state, w, 0);
for(int round = 1; round < Nr; round++) {
SubBytes(state);
ShiftRows(state);
MixColumns(state);
AddRoundKey(state, w, round);
}
// last round
SubBytes(state);
ShiftRows(state);
AddRoundKey(state, w, Nr);
for(int j = 0; j < Nb; j++) {
for(int i = 0; i < 4; i++) {
out[i + 4 * j] = state[i][j];
}
}
free(w);
free(state);
}
u8* AesDecrypt(int key_size, u8* k, u8* in, u8*out) {
/*in: encrypt_text, out : decrypt_text*/
u8** state = (u8**)malloc(sizeof(u8*) * Nb);
for(int i = 0; i < 4; i++) {
state[i] = (u8*)malloc(sizeof(u8) * 4);
}
u8** w = init(key_size, k, state, in); // w stores the expanded key
AddRoundKey(state, w, Nr);
for(int round = Nr - 1; round > 0; round--) {
InvShiftRows(state);
InvSubBytes(state);
AddRoundKey(state, w, round);
InvMixColumns(state);
}
InvShiftRows(state);
InvSubBytes(state);
AddRoundKey(state, w, 0);
for(int j = 0; j < Nb; j++) {
for(int i = 0; i < 4; i++) {
out[i + 4 * j] = state[i][j];
}
}
free(w);
free(state);
}
void display(u8* a) {
for(int i = 0; i < Nb * 4; i++)
printf("%02x", a[i]);
printf("\n");
}
int main() {
u8* encrypt_text = (u8*)malloc(sizeof(u8) * (4 * Nb));
u8* decrypt_text = (u8*)malloc(sizeof(u8) * (4 * Nb));
unsigned char plain_text[16] = "zzzzyyyyxxxxwwww";
unsigned char key_16[16] = "abcdefghijklmnop";
unsigned char key_24[24] = "abcdefghijklmnopqrstuvwx";
unsigned char key_32[32] = "abcdefghijklmnopqrstuvwxyyyyzzzz";
// keysize = 128 bits
AesEncrypt(16, key_16, plain_text, encrypt_text);
display(encrypt_text);
AesDecrypt(16, key_16, encrypt_text, decrypt_text);
display(decrypt_text);
// keysize = 192 bits
AesEncrypt(24, key_24, plain_text, encrypt_text);
display(encrypt_text);
AesDecrypt(24, key_24, encrypt_text, decrypt_text);
display(decrypt_text);
//keysize = 256 bits
AesEncrypt(32, key_32, plain_text, encrypt_text);
display(encrypt_text);
AesDecrypt(32, key_32, encrypt_text, decrypt_text);
display(decrypt_text);
}
本文作者:chchee
本文链接:https://www.cnblogs.com/chchee-blog/p/18528788
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步