advanced encryption standard,又名rijndael密码,为两位比利时数学家的名字组合。
**广义的rijndael密码的分组可以为192/256,但按照美国nist的标准,aes分组只能为128bit
分组为128bit,密钥为128/192/256bit可选,对应加密轮数10/12/14轮。
基本操作为四种:
- 字节代换(subBytes transformation) s-box,替换
- 行移位(shiftrows transformation)置换
- 列混淆(mixcolumn transformation)GF(2^8)上的多项式运算
- 轮密钥加(addroundkey)异或子密钥
以128bit密钥的加密过程为例:
1,s-box,替换,增加非线性
将128bit(16字节)的数据写成4*4大小的矩阵以方便展示和运算。
2.行移位,可以看成对每一行进行某种置换
从上至下,依次循环左移0,1,2,3字节
3.列混淆,我不确定混淆这个词是否恰当
**涉及伽罗瓦域的相关知识GF(2^8)
本质是两个4*4的矩阵相乘,但这里的乘法和加法比较怪异。
普通的矩阵乘法:
aes的列混淆,系数矩阵为内部预定义好的,s00矩阵为当前的状态矩阵,与常数矩阵相乘后获得新的s'00状态矩阵。
异或代替了正常的加法
乘法不再是3*5=15这种,而是以3的二进制形式作为系数生成一个多项式:0*x^7+0*x^6+0*x^5+0*x^4+0*x^3+0*x^2+1*x^1+1
5也是如此,然后两个多项式相乘,所得结果模一个固定的不可约多项式(irreducible polynomials)(不可约多项式本身无法被分解成更小的多项式的乘积,有点像质数),这个不可约多项式的系数已在代码中展示irreducepoly。所得的余数多项式取各项系数作为二进制数,即为3*5的结果。
选取这个多项式单纯因为他是x^8的第一个不可约多项式。任何一个x^8的不可约多项式都能起到相同的作用。
类似于质数,为了保证非0元素的逆元存在,所以要求这个多项式必须是不可约的。
多项式除法类似下图:
商quotient,x^2+2x+2
余数remainder,1
以第一行为例,左矩阵第一行[2,3,1,1]乘以右矩阵第一列[s0,s1,s2,s3]
# to prove (0x2*0x87)^(0x3*0x6e)^(0x46)^(0xa6)-->0x47
print(bin(0x2),bin(0x87),bin(0x3),bin(0x6e))
import numpy
const_matrix_0x2 = (0,0,0,0,0,0,1,0)
stat_matrix1_0x87 = (1,0,0,0,0,1,1,1)
const_matrix2_0x3 = (0,0,0,0,0,0,1,1)
stat_matrix2_0x6e = (0,1,1,0,1,1,1,0)
ret = numpy.polymul(const_matrix_0x2, stat_matrix1_0x87)
irreducepoly=(1,0,0,0,1,1,0,1,1)
q,r=numpy.polydiv(ret,irreducepoly)
print('r1',r)
ret = numpy.polymul(const_matrix2_0x3, stat_matrix2_0x6e)
q,r=numpy.polydiv(ret,irreducepoly)
print('r2',r)
print('%x'%(0b10101^0b10110010^0x46^0xa6))
# r1 [-1. 0. 1. 0. -1.]
# r2 [1. 2. 1. 1. 2. 2. 1. 0.]
# 47
**r1中的-1在mod 2的意义下等同于1
**r2中的2在mod 2的意义下等同于0
4.轮密钥加,addroundkey
异或子密钥。没啥花活儿。
密钥编排(Key Schedule)(子密钥生成过程)
待续