一、SM3
对长度为l(l<264)比特的消息m,SM3杂凑算法经过填充和迭代压缩,生成杂凑值,杂凑值长度为256比特。
初始值及常量:
IV=7380166f4914b2b9172442d7da8a0600a96f30bc163138aae38dee4db0fb0e4e
Tj= { 79cc4519 0≤j≤15;7a879d8a 16≤j≤63}
算法过程:
1)填充部分:
假设消息m的长度为l比特。首先将比特“1”添加到消息的末尾,再添加k个“0”,k是满 足l+1+k≡448mod512的最小的非负整数(其实也就是满足(l+1)%512+k = 448)。然后再添加一个64位比特串,该比特串是长度l的二进 制表示。填充后的消息m′的比特长度为512的倍数。
填充函数实现代码:
def sm3_padding(message):
# 消息长度(乘以8,将字节转化为比特为单位)
message_length = len(message) * 8
# 添加比特"1"
message += b'\x80'
# 计算填充长度k
k = 448 - (message_length + 1) % 512
# 添加k个比特"0"
message += b'\x00' * (k // 8)
# 添加64位比特串,表示消息长度
message += message_length.to_bytes(8, byteorder='big')
return message
# 测试
message = b'abc'
padded_message = sm3_padding(message)
print(padded_message)
#ls = b'abc\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18'
2)消息分组
将填充后的消息m按照512比特(64字节)进行分组,每个分组标记为B[0]、B[1]、B[2]......B[n-1],n=(l+k+65) / 512。
消息分组函数实现代码:
def group_message(message):
padded_message = message
# 将填充后的消息按照512比特(64字节)进行分组
num_groups = len(padded_message) // 64
message_groups = [padded_message[i * 64: (i + 1) * 64] for i in range(num_groups)]
return message_groups
message = b'abc\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18'
message_groups = group_message(message)
# 测试,打印分组后的消息
for i, group in enumerate(message_groups):
print(f"B[{i}]: {group}")
3)消息扩展
目的:将每个B[i]经过扩展后化为132个字,分别为W0,W1,···,W67,W′ 0,W′ 1,···,W′ 63
计算W0~W15:
将分组后每512比特(64字节)的B[i]化为16个部分,每个部分为32比特(4字节),分别记为W0, W1, ..., W15。
计算W16~67:
使用for循环,循环16~67,每个W[i]等于(W[i-16]^W[i-9]^(Wi−3 ≪15))^(Wi−13 ≪ 7)^Wi−6
计算W'0~W‘63:
W'i = W'i ^ W'[i + 4]
P1置换函数实现代码如下:
def P1(X):
left_shift_15 = (X << 15) & 0xFFFFFFFF
left_sift_23 = (X << 23) & 0xFFFFFFFF
return X ^ left_shift_15 ^ left_shift_23
消息扩展函数代码如下:
def message_expansion(B_i):
# 初始化
W = [0] * 68
W_discard = [0] * 64
# 划分W0~W16
for h in range(16):
W[h] = int.from_bytes(B_i[h*4:h*4+4], byteorder='big')
for h in range(16, 68):
W[h] = P1(W[h-16] ^ W[h-9] ^ ((W[h-3] << 15)& 0xFFFFFFFF)) ^ ((W[h-13] << 7)& 0xFFFFFFFF) ^ W[h-6]
for h in range(64):
W_discard[h] = W[h] ^ W[h + 4]
for i in W:
i = hex(i)[2:].zfill(8)
print(i,end='\n')
print('-------------------------------------')
for i in W_discard:
i = hex(i)[2:].zfill(8)
print(i,end='\n')
B_i = b'\x61\x62\x63\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18'
message_expansion(B_i)
4)迭代压缩函数
P0置换函数代码如下:
def P0(X):
return X ^ (X << 9)& 0xFFFFFFFF ^ (X << 17)& 0xFFFFFFFF
FFJ函数代码如下:
def FFJ(X, Y, Z, j):
if 0 <= j <= 15:
return X ^ Y ^ Z
elif 16 <= j <= 63:
return (X & Y) | (X & Z) | (Y & Z)
else:
raise ValueError("Invalid value of j for FFJ function")
GGJ函数代码如下:
def GGJ(X, Y, Z, j):
if 0 <= j <= 15:
return X ^ Y ^ Z
elif 16 <= j <= 63:
return (X & Y) | (~X & Z)
else:
raise ValueError("Invalid value of j for GGJ function")
待完善