题目
AES数学基础
详情可参考 现代密码学|AES数学基础|GF(2^8)有限域上的运算问题_哔哩哔哩_bilibili
(25条消息) 关于AES的列混合计算和解密流程问题_aes列混合在线计算_国科大网安二班的博客
请仔细阅读以上两个参考资料后 再来看本文
这里只涉及编程中基于AES数学基础的算法设计
首先有几个需要注意的问题:
- {}里的是一个字节 代表该字节的二进制所代表的那个系数在GF(2)的多项式
- 同时每一项相乘的结果要mod(x8+x4+x3+x+1)
- 最后的结果要mod(x4+1)
加法很简单:直接对应系数异或即可
def plus():#加法很简单 对应系数异或即可
A = input("请依次输入a(x)中x^3 x^2 x^1 x^0的系数:\n").split(" ")
B = input("请依次输入b(x)中x^3 x^2 x^1 x^0的系数:\n").split(" ")
C=[]
for i in range(4):
C.append(hex((int(A[i],16)^int(B[i],16)))[2:].zfill(2))
print("结果以x^3 x^2 x^1 x^0的次序输出:")
for i in range(4):
print(C[i],end=" ")
return C
乘法比较复杂:
d0,d1,d2,d3是通过类似于矩阵相乘的形式得到的(原因在给出的第2个链接中可以找到)
在计算每一项例如a0 b0、a3 b1相乘的过程中需要将其中一个多项式分解为x*s(x)的形式 以便于计算
例如:
{12} *{07} 分解为 {12} * {02*02 + 02 + 01} = {12} *{02}*{02} + {12} * {02} + {12}*{01}
(02 在对应二进制的多项式中 代表的就是x;同理,01 代表的就是 1;这里的加法仍然是异或运算)
那么在算法中,以此为例 :
第一次需要进行两次乘x运算 即完成 12*02*02(此处及以下都省略{})
第二次需要进行一次乘x运算 即完成12*02,同时需要与上述结果异或得到新的结果
直到第三次01的出现 (显然 01 乘 任何多项式 都等于该多项式本身) 再将12 与第二次的结果相异或得到新结果,至此结束
我们理清了这个思路后
只需要做到两步即可:
- 实现x*s(x)的算法
关于这方面核心:
具体推导过程可自行查阅 这里不阐述
def times_x(num):#实现x*b(x)
num = num<<1
bitstr = bin(num)[2:].zfill(9)#注意长度包括b7是9
bitstr_ = bitstr[1:]#取b6到0
if(bitstr[0] == "0"):#判断b7
return int(bitstr_,2)
else:
return int(bitstr_,2)^ 0b00011011
- 以矩阵形式完成乘法算法
D =[]
for i in range(4):
result = 0 # 用于记录d0,d1,d2,d3
for j in range(4):#min max 用来节约时间
# 挑选两个之中更小的那个
min_ = min(coeff_A[i][j],B[3-j])# 3-j是因为 次数递减输入系数
# 将相乘的数不断分解出x 直到无法分解
# 例如 12 * 07 = 12 * (02 * 02 + 02 + 01)
while(min_ >= 2):
#进行再一次分解之前要重置max
max_ = max(coeff_A[i][j],B[3-j])
#xnum表示此次分解需要乘x的次数
xnum = math.floor(math.log(min_,2))#floor向下取整
min_ = min_ - 2**xnum
for t in range(xnum):
max_ = times_x(max_)
result = result ^ max_# 将每次while循环的结果异或
if min_ == 1:
result = result ^ max(coeff_A[i][j],B[3-j])
#不用考虑0的情况 因为和0相乘还是等于0 而0和任何数异或还是这个数
D.append(result)
完整代码
没经过严密的验证 不保证完全正确
import math
def times_x(num):#实现x*b(x)
num = num<<1
bitstr = bin(num)[2:].zfill(9)#注意长度包括b7是9
bitstr_ = bitstr[1:]#取b6到0
if(bitstr[0] == "0"):#判断b7
return int(bitstr_,2)
else:
return int(bitstr_,2)^ 0b00011011
def times():#乘法
A = [int(i,16) for i in input("请依次输入a(x)中x^3 x^2 x^1 x^0的系数:\n").split(" ")]
B = [int(i,16) for i in input("请依次输入b(x)中x^3 x^2 x^1 x^0的系数:\n").split(" ")]
coeff_A = [ [A[3],A[0],A[1],A[2]],
[A[2],A[3],A[0],A[1]],
[A[1],A[2],A[3],A[0]],
[A[0],A[1],A[2],A[3]]]#输入的系数是以 x^3 x^2递减的次数输入的
# print(coeff_A)
D =[]
for i in range(4):
result = 0 # 用于记录d0,d1,d2,d3
for j in range(4):#min max 用来节约时间
# 挑选两个之中更小的那个
min_ = min(coeff_A[i][j],B[3-j])# 3-j是因为 次数递减输入系数
# 将相乘的数不断分解出x 直到无法分解
# 例如 12 * 07 = 12 * (02 * 02 + 02 + 01)
while(min_ >= 2):
#进行再一次分解之前要重置max
max_ = max(coeff_A[i][j],B[3-j])
#xnum表示此次分解需要乘x的次数
xnum = math.floor(math.log(min_,2))#floor向下取整
min_ = min_ - 2**xnum
for t in range(xnum):
max_ = times_x(max_)
result = result ^ max_# 将每次while循环的结果异或
if min_ == 1:
result = result ^ max(coeff_A[i][j],B[3-j])
#不用考虑0的情况 因为和0相乘还是等于0 而0和任何数异或还是这个数
D.append(result)
print("结果以x^3 x^2 x^1 x^0的次序输出:")
for i in range(4):
print(hex(D[3-i])[2:].zfill(2),end=" ")#得到的列表是d0,d1,d2,d3,因此为了顺应输入的次序逆着输出
return D
def plus():#加法很简单 对应系数异或即可
A = input("请依次输入a(x)中x^3 x^2 x^1 x^0的系数:\n").split(" ")
B = input("请依次输入b(x)中x^3 x^2 x^1 x^0的系数:\n").split(" ")
C=[]
for i in range(4):
C.append(hex((int(A[i],16)^int(B[i],16)))[2:].zfill(2))
print("结果以x^3 x^2 x^1 x^0的次序输出:")
for i in range(4):
print(C[i],end=" ")
return C
delim = int(input("请选择运算符:0.+ 1.*\n"))
if delim:
times()
else :
plus()
结果如图: