AES加解密算法
简介
密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法(实际上有所区别),是美国联邦政府采用的一种区块加密标准。
由2001年发布,用以替换DES加密技术
算法
密钥长度: 固定为128b,196b,256b
区块长度: 固定为128b
加密算法:
密钥与明文区块将被排列为两张4X4的矩阵表
其中密钥的矩阵将以列为单位扩充为44长度的字列表,前四个字为初始密钥
def aesEncrypt(m, w)
AddRoundKey #轮密钥加 w[0:4], 初始密钥
for i inrange(10):
subBytes #字节代换
shiftRows #行移位
mixColumns #列混合
AddRoundKey #轮密钥加 w[(i+1)*4:(i+2)*4]
字节代换
字节代换其实质为查表操作,加密解密各一张表,称之为S盒、逆S盒
比如进行S盒字节代换,源码为0x34,则查找行3列4位置的数据0x18,则该次字节代换0x34==>0x18, 逆S盒操作之时,查找行1列8的数据0x18==>0x34
S盒
逆S盒
行移位
第一届状态矩阵为明文矩阵
加密时候:将状态矩阵左移x位,移位步数为该行行数
line1 = line1[0:4]
line2 = line2[1:4] + line2[0:1]
line3 = line2[2:4] + line2[0:2]
line4 = line2[3:4] + line2[0:3]
解密时候:将状态矩阵右移x位,移位步数为该行行数
line1 = line1[0:4]
line2 = line2[3:4] + line2[0:3]
line3 = line2[2:4] + line2[0:2]
line4 = line2[1:4] + line2[0:1]
列混合
对状态矩阵进行跟新,让状态矩阵与一个固定矩阵相乘
S’0j=(2S0j)⊕(3S1j)⊕S2j⊕S3j
S’1j= S0j⊕(2S1j)⊕(3S2j)⊕S3j
S’2j= S0j⊕S1j⊕(2S2j)⊕(3S3j)
S’3j=(3S0j)⊕S1j⊕S2j⊕S(23j)
其中乘法情况分为四种基本运算
S1 = 1S==>S
S2 = 2S==>(S<<1)⊕0x1D
S3 = 3S==>S⊕(2S)
S4 = 4S==>2(2*S)
此处为GF二元运算,非平常意义的乘法
uint8_t gmult(uint8_t a, uint8_t b) {
uint8_t p = 0, i = 0, hbs = 0;
for (i = 0; i < 8; i++) {
if (b & 1) {
p ^= a;
}
hbs = a & 0x80;
a <<= 1;
if (hbs) a ^= 0x1b; // 0000 0001 0001 1011
b >>= 1;
}
return (uint8_t)p;
}
列混合逆运算
轮密钥加
轮密钥矩阵(字W[0:44])与状态矩阵进行亦或得到新的状态矩阵
轮密钥扩展
初始密钥可写为4X4的矩阵,以列为单位组成4个初始字,记为W[0:4],
扩展算法:
for i in range(4,44):
if i%4 != 0:
W[i]=W[i-4]⨁W[i-1]
else:
W[i]=W[i-4]⨁T(W[i-1])
关于T算法
-
进行字循环,左移四个字节,即左移一个字, 左边数据放到右边,比如:
[W0, W1, W2, W3]==>[W1, W2, W3, W0] -
字节代换:
-
轮常量亦或
首先获取轮常量
uint8_t R[] = {0x02, 0x00, 0x00, 0x00};
//i为当前轮数
uint8_t * Rcon(uint8_t i) {
if (i == 1) {
R[0] = 0x01; // x^(1-1) = x^0 = 1
} else if (i > 1) {
R[0] = 0x02;
i--;
while (i-1 > 0) {
R[0] = gmult(R[0], 0x02);//
i--;
}
}
return R;
}