如何实现AES密码算法?
背景
前些年美国国标局(好像是这个单位)公开征集一种128位分组密码算法用以替代使用了20年的DES。由两位比利时密码学家设计的Rijndael算法最终胜出。可以访问作者的网站。
(1)多项式加法 多项式加法即按位做异或运算。例如0x57 + 0x83 = 01010111 XOR 10000011 = 11010100 = 0xD4。 (2)多项式乘法 GF(2n)中的乘法是多项式的模2乘积通过免去进位,再模一个次数为n的不可约多项式约化得到,不可约多项式我理解的和自然数域中的素数相对应,都是有不可再分解的特点。例如下面GF(23)的例子: f(x)*g(x) = (x2+x)(x2+x+1) mod (x3+x+1) = (x4+2x3+2x2+x) mod (x3+x+1) 系数是二的直接约掉,实际上这里是模2加法 = (x4+x) mod (x3+x+1) = x2+1
Rijindael选用8次不可约多项式x8+x4+x3+x+1,可用元组(100011011)或十六进制数0x11B表示。用这个多项式的理由听起来比较有意思,作者说是在一本书上有一堆8次不可约多项式,第一个是0x11B就用它了,FT吧。f(x)乘以x+1(或‘03’)的乘法分解成f(x)*2+1,最后模m(x)约化: f ^= f << 1; //乘2加1 if(f & 0x100) f ^= 0x11B; //模m(x)约化 在GF(28)中的两个多项式f和h的乘法可通过用对数加速:设g(x)为GF(28)的一个生成多项式,所谓生成多项式就是数组的256个元素的值就是0-255的排列,则存在m和n使得f=gm,h=gn,则f*h=gm+x mod m(x)。有了这个公式我们就可以把多项式乘法转为加法来算,具体说来就是构造对数表和反对数表,如下图:
对数表的构造: 1. 构造多项式g(x)=x+1的255个幂存入alog表中 alog[0] = 1; for (i = 1; i < 256; i++) { j = (alog[i-1] << 1) ^ alog[i-1]; //x*3=x*2+1 if ((j & 0x100) != 0) // 如果超过255,需要约化 j ^= ROOT; alog[i] = j; } 2. 在log表中存放对底g(x)的对数 for (i = 1; i < 255; i++) log[alog[i]] = i; 再构造alog和log之后,乘法运算可以一步完成alog[ (log[a]+log[b]) % 255 ] 。 实际上实现多项式乘法的方法有很多种,在msdn搜AES可以查到一篇写c#实现的,它的乘法算法也是一种很经典的方法。用对数表的方法好理解,最重要的是查表速度快。
S盒和反向S盒的实现
(1) 初始化S盒,按升序排列的字节表示
Tbox的构造 for (t = 0; t < 256; t++) { s = Sbox[t]; Tbox1[t] = mul4(s, G[0]); Tbox2[t] = mul4(s, G[1]); Tbox3[t] = mul4(s, G[2]); Tbox4[t] = mul4(s, G[3]); s = inSbox[t]; Tbox5[t] = mul4(s, iG[0]); Tbox6[t] = mul4(s, iG[1]); Tbox7[t] = mul4(s, iG[2]); Tbox8[t] = mul4(s, iG[3]); } G矩阵可以在作者的文献中查到,iG是G在GF(28)的逆。 在加解密过程中,加密用Tbox1-4,解密用Tbox5-8,前9轮用T,最后一轮用Sbox。但是要注意调用顺序,为了实现列混淆,具体顺序参看那个列混淆的公式。