设计思路:
在设计算法之前,我们先编写一些功能模块。
- 定义函数left()和right(),通过参数传递,分别返回参数的first and last
def left(Str):
return Str[:int(len(Str) / 2)]
def right(Str):
return Str[int(len(Str) / 2):]
- L⊗RL⊗R运算即L×R mod RCi∈F24L×R mod RCi∈F24,我们通过函数modular_Reduction()实现该功能,最后返回四位二进制位
def modular_Reduction(str1, str2, px="10011"):
# 两个二进制相乘的结果 考虑系数偶数次为0
res = "00000000"
for i in range(len(str2)):
if int(str2[i]) == 1:
str1_temp = str1
for j in range(len(str2)-i-1):
str1_temp = str1_temp+"0"
res = str_xor(str1=res, str2=str1_temp, len=8)
# 获得乘积 接下里进行模约减
for i in range(int(len(res)/2)):
if int(res[i]) == 0:
res = res
else:
j = len(res) - i - 5
px_temp = px
for k in range(j):
px_temp = px_temp + "0"
res = str_xor(str1=res, str2=px_temp, len=8)
return res[-4:]
- L⊕RL⊕R运算即LL 与按位异或运算,我们通过函数str_xor()实现该功能;
def str_xor(str1, str2, len=4):
num1 = int(str1, base=2)
num2 = int(str2, base=2)
return int2bin(int(bin(num1 ^ num2), 2), len)
- 由于题目中大多数是八位二进制位,因此十进制转为二进制后当前位数小于8时,我们通过函数int2bin()用0补齐:
def int2bin(n, count=8):
return "".join([str((n >> y) & 1) for y in range(count-1, -1, -1)])
- 在求K值过程中,Round的第一步即W<<<3W<<<3,通过函数left_move()实现:
def left_move(Str, n):
return Str[n:] + Str[:n]
- 在SubBytes环节中,有一项求解当前参数在mod p(x)mod p(x)下的逆元,理论上应用扩展欧几里得算法可以求解,但是涉及到F24F24算法难度会有所提升,切考虑到目标参数是四位二进制位,仅有24=1624=16种可能解,因此我们通过函数select_inv()暴力求解:
def select_inv(Str):
dict = {'0000': '0000', '0001': '0001', '0010': '1001','0011': '1110',
'0100': '1101','0101': '1011','0110': '0111','0111': '0110',
'1000': '1111','1001': '0010','1010': '1100','1011': '0101',
'1100': '1010','1101': '0100','1110': '0100','1111': '1000'}
return dict[Str]
在六轮加密中,分别用到了密钥K0-K5,因此在正式加密过程中,我们第一步要先求出密钥。利用初始密钥K,通过函数get_K()计算出K0-K5。
def get_K(k):
w0 = k[:8]
w1 = k[8:16]
w2 = k[16:24]
w3 = k[24:]
RC1 = "00000011"
RC2 = "00000110"
RC3 = "00001100"
RC4 = "00001011"
RC5 = "00000101"
k0 = get_Matrix_K(w0, w1, w2, w3)
# get K1
T = left_move(w3, 3)
T = subBytes(T[:4]) + subBytes(T[4:])
T = str_xor(T, RC1, len=8)
w4 = str_xor(w0, T, len=8)
w5 = str_xor(w1, w4, len=8)
w6 = str_xor(w2, w5, len=8)
w7 = str_xor(w3, w6, len=8)
k1 = get_Matrix_K(w4, w5, w6, w7)
# get K2
T = left_move(w7, 3)
T = subBytes(T[:4]) + subBytes(T[4:])
T = str_xor(T, RC2, len=8)
w8 = str_xor(w4, T, len=8)
w9 = str_xor(w5, w8, len=8)
w10 = str_xor(w6, w9, len=8)
w11 = str_xor(w7, w10, len=8)
k2 = get_Matrix_K(w8, w9, w10, w11)
# get K3
T = left_move(w11, 3)
T = subBytes(T[:4]) + subBytes(T[4:])
T = str_xor(T, RC3, len=8)
w12 = str_xor(w8, T, len=8)
w13 = str_xor(w9, w12, len=8)
w14 = str_xor(w10, w13, len=8)
w15 = str_xor(w11, w14, len=8)
k3 = get_Matrix_K(w12, w13, w14, w15)
# get K4
T = left_move(w15, 3)
T = subBytes(T[:4]) + subBytes(T[4:])
T = str_xor(T, RC4, len=8)
w16 = str_xor(w12, T, len=8)
w17 = str_xor(w13, w16, len=8)
w18 = str_xor(w14, w17, len=8)
w19 = str_xor(w15, w18, len=8)
k4 = get_Matrix_K(w16, w17, w18, w19)
# get K5
T = left_move(w19, 3)
T = subBytes(T[:4]) + subBytes(T[4:])
T = str_xor(T, RC5, len=8)
w20 = str_xor(w16, T, len=8)
w21 = str_xor(w17, w20, len=8)
w22 = str_xor(w18, w21, len=8)
w23 = str_xor(w19, w22, len=8)
k5 = get_Matrix_K(w20, w21, w22, w23)
return k0, k1, k2, k3, k4, k5
其中函数SubBytes()定义如下:
def subBytes(Str):
tmp = select_inv(Str)
x3 = str_xor(str(int(tmp[3], base=2) & 1), "1", len=1)
x2 = str_xor(str(int(tmp[3], base=2) & 1), str(int(tmp[2], base=2) & 1), len=1)
x1 = str_xor(str_xor(tmp[0], tmp[1], len=1), str_xor(tmp[2], tmp[3], len=1), len=1)
x0 = str_xor(str_xor(tmp[1], tmp[2], len=1), str_xor(tmp[0], "1", len=1), len=1)
return x0 + x1 + x2 + x3
函数get_Matrix_K()定义如下:
def get_Matrix_K(w0, w1, w2, w3):
K_00 = str_xor(str_xor(modular_Reduction(left(w0), right(w0)), left(w0)), right(w0))
K_10 = str_xor(str_xor(modular_Reduction(left(w1), right(w1)), left(w1)), right(w1))
K_01 = str_xor(str_xor(modular_Reduction(left(w2), right(w2)), left(w2)), right(w2))
K_11 = str_xor(str_xor(modular_Reduction(left(w3), right(w3)), left(w3)), right(w3))
return K_00, K_01, K_10, K_11
在该过程中,由于题中规定RCi=xi+3(modx4+x+1)RCi=xi+3(modx4+x+1),即RC1,…,RC5RC1,…,RC5固定不变,虽然可以通过代码计算,但是性价比不高,因此直接在代码里人工初始化RC1,…,RC5RC1,…,RC5。
获得密钥K0−K5K0−K5后,通过函数roundd()分别计算中间变量L1 R1−L6 R6L1 R1−L6 R6:
def roundd(l, r, k):
# SubBytes
res = subBytes(r[:4]) + subBytes(r[8:12]) + subBytes(r[4:8]) + subBytes(r[12:])
# MultRoundKey
mrk00 = str_xor(modular_Reduction(k[0], res[:4], px="10011"), modular_Reduction(k[1], res[8:12], px="10011"), len=4)
mrk01 = str_xor(modular_Reduction(k[0], res[4:8], px="10011"), modular_Reduction(k[1], res[12:], px="10011"), len=4)
mrk10 = str_xor(modular_Reduction(k[2], res[:4], px="10011"), modular_Reduction(k[3], res[8:12], px="10011"), len=4)
mrk11 = str_xor(modular_Reduction(k[2], res[4:8], px="10011"), modular_Reduction(k[3], res[12:], px="10011"), len=4)
# MixColumns
mc00 = str_xor(modular_Reduction("0011", mrk00, px="10011"), modular_Reduction("0111", mrk10, px="10011"), len=4)
mc01 = str_xor(modular_Reduction("0011", mrk01, px="10011"), modular_Reduction("0111", mrk11, px="10011"), len=4)
mc10 = str_xor(modular_Reduction("0100", mrk00, px="10011"), modular_Reduction("0011", mrk10, px="10011"), len=4)
mc11 = str_xor(modular_Reduction("0100", mrk01, px="10011"), modular_Reduction("0011", mrk11, px="10011"), len=4)
# ShiftRows # 变换状态矩阵
a = mc00 + mc01 + mc11 + mc10
l1 = r
r1 = str_xor(l, mc00 + mc11 + mc01 + mc10, len=16)
return a, l1, r1
得到L6 R6L6 R6后,整合上面函数为ek,继而得到密文C:
def ek(iv, k):
K0, K1, K2, K3, K4, K5 = get_K(k)
L0 = iv[:16]
R0 = iv[16:]
# round0
print("Round 0:")
A, L1, R1 = roundd(L0, R0, K0)
print("L1:", L1)
print("R1:", R1)
# round1
print("Round 1:")
A, L2, R2 = roundd(L1, R1, K1)
print("L2:", L2)
print("R2:", R2)
# round2
print("Round 2:")
A, L3, R3 = roundd(L2, R2, K2)
print("L3:", L3)
print("R3:", R3)
# round3
print("Round 3:")
A, L4, R4 = roundd(L3, R3, K3)
print("L4:", L4)
print("R4:", R4)
# round4
print("Round 4:")
A, L5, R5 = roundd(L4, R4, K4)
print("L5:", L5)
print("R5:", R5)
# round5
print("Round 5:")
A, L6, R6 = roundd(L5, R5, K5)
print("L6:", L6)
print("R6:", R6)
return R6 + L6
Main()中重复上述步骤得到后续密文:
if __name__ == "__main__":
M = input("Please input M:")
K = input("Please input K:")
if len(K) != 32:
print("Error K!")
IV = input("Please input IV:")
if len(IV) != 32:
print("Error IV!")
if len(M) == 96:
M1 = M[:32]
M2 = M[32:64]
M3 = M[64:]
print()
print("Ek(IV)...")
ek_IV = ek(IV, K)
c1 = str_xor(ek_IV, M1, len=32)
print()
print("Ek(C1)...")
ek_c1 = ek(c1, K)
c2 = str_xor(ek_c1, M2, len=32)
print()
print("Ek(C2)...")
ek_c2 = ek(c2, K)
c3 = str_xor(ek_c2, M3, len=32)
print()
print("C1||C2||C3:", c1, "||", c2, "||", c3)
elif len(M) == 128:
M1 = M[:32]
M2 = M[32:64]
M3 = M[64:96]
M4 = M[96:]
print()
print("Ek(IV)...")
ek_IV = ek(IV, K)
c1 = str_xor(ek_IV, M1, len=32)
print()
print("Ek(C1)...")
ek_c1 = ek(c1, K)
c2 = str_xor(ek_c1, M2, len=32)
print()
print("Ek(C2)...")
ek_c2 = ek(c2, K)
c3 = str_xor(ek_c2, M3, len=32)
print()
print("Ek(C3)...")
ek_c3 = ek(c3, K)
c4 = str_xor(ek_c3, M4, len=32)
print()
print("C1||C2||C3||C4:", c1, "||", c2, "||", c3, "||", c4)
elif len(M) == 160:
M1 = M[:32]
M2 = M[32:64]
M3 = M[64:96]
M4 = M[96:128]
M5 = M[128:]
print()
print("Ek(IV)...")
ek_IV = ek(IV, K)
c1 = str_xor(ek_IV, M1, len=32)
print()
print("Ek(C1)...")
ek_c1 = ek(c1, K)
c2 = str_xor(ek_c1, M2, len=32)
print()
print("Ek(C2)...")
ek_c2 = ek(c2, K)
c3 = str_xor(ek_c2, M3, len=32)
print()
print("Ek(C3)...")
ek_c3 = ek(c3, K)
c4 = str_xor(ek_c3, M4, len=32)
print()
print("Ek(C4)...")
ek_c4 = ek(c4, K)
c5 = str_xor(ek_c4, M5, len=32)
print()
print("C1||C2||C3||C4||C5:", c1, "||", c2, "||", c3, "||", c4, "||", c5)