2021SC@SDUSC
本章承接上一周的文章,对AES算法实现进行简单的实现,这里未涉及CUDA/GPU技术。只是先对AES算法进行一般程序语言的实现做一个简单的了解。
一、声明AES类
采用面向对象编程,声明AES类对象,将加密过程中各种功能函数进行声明,使代码结构清晰,便于管理。
class Aes {
public:
Aes();
~Aes();
Aes(int keysize,unsigned char* keyBytes); //构造函数用密钥长度keySize和密钥内容keyBytes作为参数。
void Cipher(unsigned char* input, unsigned char* output); // 加密函数,input 为16位为要加密的明文
InvCipher(); // 解密函数,input 为16位要解密的密文
private:
int Nb; int Nk; int Nr;
unsigned char key[32];
unsigned char w[16*15];
SetNbNkNr(int keySize); //设置轮数
AddRoundKey(int round); //轮密钥加
SubBytes(); //S盒字节代换
InvSubBytes(); //逆S盒字节代换
ShiftRows(); //行移位
InvShiftRows();
MixColumns(); //列混淆
InvMixColumns();
KeyExpansion(); //密钥扩展
unsigned char* SubWord(unsigned char* word); //密钥S盒字代换
unsigned char* RotWord(unsigned char* word); //密钥移位
}
二、成员函数的实现
2.1 SetNbNkNr(int keySize) 迭代分组列数、密钥列数、迭代次数设置函数
功能描述:因为AES分组长度为128 bits,Nb固定为4。再根据界面密钥长度窗口keySize的选择,判断是密钥是128、192、256比特。因为在上一章只讨论AES-128,所以这里只讨论密钥是128字节的情况,因此NK=4,Nr=10。
Aes::SetNbNkNr(int keySize)
{
Nb=4;
if(keySize==Bits128)
{
Nk=4; //4*4字节,128位密钥,10轮加密
Nr=10;
}else{
//剩余两种情况192 256这里不写
}
}
2.2 Aes(int keysize,unsigned char* keyBytes) 构造函数
功能描述:实现了设置密钥块数,轮数,以及为密钥扩展提前做的初始化。
Aes::Aes(int keysize,unsigned char* keyBytes)
{
SetNbNkNr(keysize); //设置密钥块数,轮数
memcpy(key,keyBytes,keysize); //字符串拷贝函数,把keyBytes的keysize个字符复制到key中
KeyExpansion(); //密钥扩展,必须提前做的初始化
}
2.3 KeyExpansion() 密钥扩展函数
功能描述:加密和解密过程分别需要Nr+1个子密钥,即11个(包括原密钥在内,扩展10个轮密钥)。所以需要对密钥进行扩展。
实现方式:主密钥的扩展首先将原密钥拷贝,并按一维数组排成4*Nk矩阵,然后取Nk列,进行RotWord()移位变换,将第一位移到第四位,再进行SubWord() 字节代换,最后再和上一个密钥的第1列做模二加法,得到新的子密钥块的第1列密钥,然后第2、3、4列是直接由前一列和上一子密钥模二加法得到。
Aes::KeyExpansion()
{
memset(w,0,16*15);
for(int row=0;row<Nk;row++) //拷贝seed 密钥
{
w[4*row+0] = key[4*row];
w[4*row+1] = key[4*row+1];
w[4*row+2] = key[4*row+2];
w[4