① 逆行变换-InvShiftRows()
上面讲到ShiftRows()是对矩阵的每一行进行循环左移,所以InvShiftRows()是对矩阵每一行进行循环右移。
② 逆 S 盒变换-InvSubBytes()
与 S 盒变换一样,也是查表,查表的方式也一样,只不过查的是另外一个置换表(S-Box的逆表)。
③ 逆列变换-InvMixColumns()
与列变换的方式一样,只不过计算公式的系数矩阵发生了变化。如下图:
好了,AES 解密到这里也讲完了。只要写出三个逆变换的函数,然后根据伪代码就很容易实现 AES 解密算法了。
三、C++实现
下面我用 C++ 实现 AES 的加密和解密算法,并实现了对文件的加密和解密。这里我使用 C++ STL 的bitset定义了两个类型:byte和word。需要提到的是,对于有限域上的乘法,我们既可以通过查表(6个结果表),也可以写一个函数来实现。当然,查表的效率会更高,但考虑到贴代码,这里我就用一个函数来实现的。
下面是 AES-128 对一个 128 位数据加密和解密的源代码:
/*************************************************************************
> File Name: AEScpp
> Author: SongLee
> E-mail: lisongshine@qqcom
> Created Time: 2014年12月12日 星期五 20时15分50秒
> Personal Blog: http://www.easck.com/>
可见,测试结果和预期输出相同,表明对数据的加密和解密成功!!!
下面我们来写 AES 对文件的加密和解密,在对 128 位的数据加解密成功以后,对文件的加解密就很简单了!只需要每次读 128 位,加密以后,将 128 位的密文写入另外一个文件…如此循环,直到文件尾。下面是对一张图片进行 AES 加密和解密的测试代码(效率先不管了,有时间我再优化):
//#include <fstream>
typedef bitset<8> byte;
typedef bitset<32> word;
/**
* 将一个char字符数组转化为二进制
* 存到一个 byte 数组中
*/
void charToByte(byte out[16], const char s[16])
{
for(int i=0; i<16; ++i)
for(int j=0; j<8; ++j)
out[i][j]= ((s[i]>>j) & 1);
}
/**
* 将连续的128位分成16组,存到一个 byte 数组中
*/
void divideToByte(byte out[16], bitset<128>& data)
{
bitset<128> temp;
for(int i=0; i<16; ++i)
{
temp = (data << 8*i) >> 120;
out[i] = tempto_ulong();
}
}
/**
* 将16个 byte 合并成连续的128位
*/
bitset<128> mergeByte(byte in[16])
{
bitset<128> res;
resreset(); // 置0
bitset<128> temp;
for(int i=0; i<16; ++i)
{
temp = in[i]to_ulong();
temp <<= 8*(15-i);
res |= temp;
}
return res;
}
int main()
{
string keyStr = "abcdefghijklmnop";
byte key[16];
charToByte(key, keyStrc_str());
// 密钥扩展
word w[4*(Nr+1)];
KeyExpansion(key, w);
bitset<128> data;
byte plain[16];
// 将文件 flowerjpg 加密到 ciphertxt 中
ifstream in;
ofstream out;
inopen("D://flowerjpg", ios::binary);
outopen("D://ciphertxt", ios::binary);
while(inread((char*)&data, sizeof(data)))
{
divideToByte(plain, data);
encrypt(plain, w);
data = mergeByte(plain);
outwrite((char*)&data, sizeof(data));
datareset(); // 置0
}
inclose();
outclose();
// 解密 ciphertxt,并写入图片 flowerjpg
inopen("D://ciphertxt", ios::binary);
outopen("D://flowerjpg", ios::binary);
while(inread((char*)&data, sizeof(data)))
{
divideToByte(plain, data);
decrypt(plain, w);
data = mergeByte(plain);
outwrite((char*)&data, sizeof(data));
datareset(); // 置0
}
inclose();
outclose();
return 0;
}










