AES(Advanced Encryption Standard)是目前应用最普遍的对称加密算法之一,由于其高强度的加密算法、易于实现、且能够应对不断出现的攻击手段,在许多领域得到广泛的应用。AES算法基于分组密码结构,将明文按照特定的分组长度进行块加密,之后结合轮函数(Round Function)进行多轮加密、单轮加密和最后一轮加密(Final Round)。在此我们将对AES加密算法的基本步骤进行详细讨论。
一、密钥扩展(Key Expansion)
密钥扩展是AES加密算法的一个重要步骤,同时也是差分攻击(Differential Attack)和线性攻击(Linear Attack)的主要攻击点之一。在该步骤中,算法会将加密密钥扩展为一个与明文分组长度(128位)相等的密钥表(Key Schedule)。密钥扩展过程中,会根据初始密钥进行多轮操作,以生成用于加密的子密钥。在扩展密钥时我们需要注意狄利克雷置换、S-Box替代以及轮常数的处理。
以下是密钥扩展的示例代码:
// 密钥扩展 void KeyExpansion(unsigned char* key, unsigned char w[][4][4]) { unsigned char temp[4]; unsigned int i,j; //密钥长度(字节)和轮数 int Nk = 4; int Nb = 4; int Nr = 10; //密钥扩展主循环 for(i = 0; i < Nk; i++) { w[i][0][0] = key[4*i]; w[i][1][0] = key[4*i+1]; w[i][2][0] = key[4*i+2]; w[i][3][0] = key[4*i+3]; } for(i = Nk; i < Nb * (Nr+1); i++) { for(j = 0; j < 4; j++) { temp[j]=w[i-1][j][0]; } if(i % Nk == 0) { //D字的补充和Rcon[x],其中x=i/Nk,Rcon[x]表示x轮常数 RotWord(temp); SubWord(temp); temp[0] ^= Rcon[(i/Nk)]; } else if(Nk > 6 && i%Nk == 4) { //针对256位加密密钥的操作 SubWord(temp); } for(j = 0; j < 4; j++) { w[i][j][0] = w[i-Nk][j][0] ^ temp[j]; } } }
二、初始轮(Initial Round)
初始轮是AES加密算法的第一轮加密,它涉及到明文和密钥的初始化以及AddRoundKey操作。在该轮中,AES算法将明文块与扩展密钥表进行一次异或运算作为初始置换操作。
以下是初始轮的示例代码:
// 初始加密轮 void InitialRound(unsigned char state[][4], unsigned char key[][4]) { unsigned char temp_state[4][4]; int i,j; //密钥与明文异或 AddRoundKey(state, key, temp_state); //保存结果 for(i=0;i<4;i++) { for(j=0;j<4;j++) { state[i][j]=temp_state[i][j]; } } }
三、多轮加密(Rounds)
多轮加密是AES加密算法的核心步骤之一,其中包含多轮轮函数(Round Function)。每一轮当中都包含MixColumns、ShiftRows、SubBytes和AddRoundKey四项操作。在进行多轮加密过程时,算法会采用类似于初始轮的操作,将扩展密钥表与明文异或,并依次执行每一轮的操作。每执行一轮操作后,就会得到一个新的状态,并将这个状态作为第二轮操作的初始状态。
以下是多轮加密的示例代码:
void Rounds(unsigned char state[][4], unsigned char w[][4][4]) { int Nr=10; int round; for(round=0;round四、最后一轮(Final Round)
最后一轮加密操作与之前的多轮加密略有不同,最后一轮操作中不再执行MixColumns操作,而是直接执行ShiftRows、SubBytes和AddRoundKey操作。最后一轮操作的输出为加密后的密文。
以下是最后一轮的示例代码:
void FinalRound(unsigned char state[][4], unsigned char w[][4][4], unsigned char cipher[][4]) { int i,j; SubBytes(state); ShiftRows(state); AddRoundKey(state, w[10], state); //保存加密结果 for(i=0;i<4;i++) { for(j=0;j<4;j++) { cipher[j][i]=state[i][j]; } } }五、解密操作
解密操作是AES加密算法的一个重要环节,需要逆向执行加密操作才能得到正确的明文。解密操作中每轮操作所使用的子密钥在加密过程中也是反向使用的。在密码表的倒数第二个密钥块上加上密文,然后逆向运算剩余的加密轮即可得到明文。
以下是解密操作的示例代码:
void DecryptAES(unsigned char* ciphertext, int ciphertext_len, unsigned char* key, unsigned char* plaintext) { int Nb = 4; int Nr = 10; int i,j; unsigned char state[4][4]; unsigned char w[Nb * (Nr + 1)][4][4]; KeyExpansion(key, w); //密钥扩展 for(i=0;i= 1; round--) { AddRoundKey(state, w[round*Nb], state); InvMixColumns(state); InvShiftRows(state); InvSubBytes(state); } AddRoundKey(state, w[0], state); for(j=0;j<16;j++) { plaintext[i+j] = state[j%4][j/4]; } } }