SM3、SM4算法学习记录(包含算法过程及相应代码 python语言)

一、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")

待完善

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是Python中实现sm3算法代码示例: ```python import struct import hashlib class SM3Hash: def __init__(self): self.iv = [0x7380166F, 0x4914B2B9, 0x172442D7, 0xDA8A0600, 0xA96F30BC, 0x163138AA, 0xE38DEE4D, 0xB0FB0E4E] self.tj = [] for i in range(0, 16): self.tj.append(0x79CC4519) for i in range(16, 64): self.tj.append(0x7A879D8A) self.A, self.B, self.C, self.D, self.E, self.F, self.G, self.H = self.iv[0], self.iv[1], self.iv[2], self.iv[3], self.iv[4], self.iv[5], self.iv[6], self.iv[7] def _CF(self, X): W = [] for i in range(0, 16): W.append(X[i]) for i in range(16, 68): W.append(self._P1(W[i-16] ^ W[i-9] ^ (self._ROTATE_LEFT(W[i-3], 15))) ^ (self._ROTATE_LEFT(W[i-13], 7)) ^ W[i-6]) for i in range(68, 64): W.append(self._P1(W[i-16] ^ W[i-9] ^ (self._ROTATE_LEFT(W[i-3], 15))) ^ (self._ROTATE_LEFT(W[i-13], 7)) ^ W[i-6] ^ W[i-64]) A, B, C, D, E, F, G, H = self.A, self.B, self.C, self.D, self.E, self.F, self.G, self.H for i in range(0, 64): SS1 = self._ROTATE_LEFT((self._ROTATE_LEFT(A, 12) + E + self._ROTATE_LEFT(self.tj[i], i % 32)) & 0xFFFFFFFF, 7) SS2 = SS1 ^ self._ROTATE_LEFT(A, 12) TT1 = (self._FFj(A, B, C, i) + D + SS2 + W[i]) & 0xFFFFFFFF TT2 = (self._GGj(E, F, G, i) + H + SS1 + W[i]) & 0xFFFFFFFF D = C C = self._ROTATE_LEFT(B, 9) B = A A = TT1 H = G G = self._ROTATE_LEFT(F, 19) F = E E = self._P0(TT2) self.A = (self.A + A) & 0xFFFFFFFF self.B = (self.B + B) & 0xFFFFFFFF self.C = (self.C + C) & 0xFFFFFFFF self.D = (self.D + D) & 0xFFFFFFFF self.E = (self.E + E) & 0xFFFFFFFF self.F = (self.F + F) & 0xFFFFFFFF self.G = (self.G + G) & 0xFFFFFFFF self.H = (self.H + H) & 0xFFFFFFFF def _P0(self, X): return X ^ self._ROTATE_LEFT(X, 9) ^ self._ROTATE_LEFT(X, 17) def _P1(self, X): return X ^ self._ROTATE_LEFT(X, 15) ^ self._ROTATE_LEFT(X, 23) def _FFj(self, X, Y, Z, j): if j >= 0 and j <= 15: return X ^ Y ^ Z else: return (X & Y) | (X & Z) | (Y & Z) def _GGj(self, X, Y, Z, j): if j >= 0 and j <= 15: return X ^ Y ^ Z else: return (X & Y) | (~X & Z) def _ROTATE_LEFT(self, x, n): return (((x) << (n)) & 0xFFFFFFFF) | ((x) >> (32-(n))) def _padding(self, data): length = len(data) * 8 data += b'\x80' data += b'\x00' * (((56 - (length + 8) % 64) % 64) - 1) data += struct.pack('>Q', length) return data def update(self, data): data = self._padding(data) for i in range(0, len(data), 64): block = data[i:i+64] X = [] for j in range(0, 16): X.append(struct.unpack('>I', block[j*4:j*4+4])[0]) self._CF(X) def digest(self): return struct.pack('>IIIIIIII', self.A, self.B, self.C, self.D, self.E, self.F, self.G, self.H) def hexdigest(self): return self.digest().hex() def sm3(data): h = SM3Hash() h.update(data) return h.hexdigest() message = b'This is a test message.' hash_value = sm3(message) print(hash_value) ``` 需要注意的是,在使用时需要将待哈希的数据转换为字节串传入`sm3`函数中。另外,在实现过程中,需要使用一些位运算的技巧,详情请参考SM3算法的相关文献。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值