SM3算法 (python)

初步学习python可能有些语法不完善;
根据国密SM3文档编写,可能有误,请指正!
国密局SM3文档地址:302a3ada057c4a73830536d03e683110.pdf (sca.gov.cn)

class SM3(object):

    def __init__(self, hex_string):
        self.hex_string = hex_string
        self.bin_string = bin(int(hex_string, 16))[2:].zfill(4*len(hex_string))
        self.IV = '7380166f4914b2b9172442d7da8a0600a96f30bc163138aae38dee4db0fb0e4e'
        self.T = ['79cc4519'] * 16 + ['7a879d8a'] * 48
        self.B = []
        self.W = [''] * 68
        self.W_ = [''] * 64

    @staticmethod
    # 循环左移
    def shift_to_left(string, num):
        return string[num % len(string):] + string[:num % len(string)]

    @staticmethod
    # 异或
    def x_o_r(string_to_number_list):
        result = 0
        for i in range(len(string_to_number_list)):
            result = result ^ string_to_number_list[i]
        return bin(result)[2:]

    @staticmethod
    # 取反
    def n_o_t(string):
        op1 = '1' * len(string)
        op2 = string
        result = bin(int(op1, 2) - int(op2, 2))[2:].zfill(len(string))
        return result

    @staticmethod
    def ff(j, x, y, z):
        if 0 <= j <= 15:
            result = SM3.x_o_r([int(x, 2), int(y, 2), int(z, 2)]).zfill(32)
        else:
            result = bin((int(x, 2) & int(y, 2)) | (int(x, 2) & int(z, 2)) | (int(y, 2) & int(z, 2)))[2:].zfill(32)
        return result

    @staticmethod
    def gg(j, x, y, z):
        if 0 <= j <= 15:
            result = SM3.x_o_r([int(x, 2), int(y, 2), int(z, 2)]).zfill(32)
        else:
            result = bin((int(x, 2) & int(y, 2)) | (int(SM3.n_o_t(x), 2) & int(z, 2)))[2:].zfill(32)
        return result

    @staticmethod
    def p0(x):
        result = SM3.x_o_r([int(x, 2), int(SM3.shift_to_left(x, 9), 2), int(SM3.shift_to_left(x, 17), 2)]).zfill(32)
        return result

    @staticmethod
    def p1(x):
        result = SM3.x_o_r([int(x, 2), int(SM3.shift_to_left(x, 15), 2), int(SM3.shift_to_left(x, 23), 2)]).zfill(32)
        return result

    def cf(self, j, v, b):
        abcdefgh = [''] * 8
        for i in range(8):
            abcdefgh[i] = v[i*32:i*32+32]
        ss1 = SM3.shift_to_left(bin(int(SM3.shift_to_left(abcdefgh[0], 12), 2) + int(abcdefgh[4], 2) +
                                    int(SM3.shift_to_left(self.T[j], j % 32), 2))[2:].zfill(32)[-32:], 7)
        ss2 = SM3.x_o_r([int(ss1, 2), int(SM3.shift_to_left(abcdefgh[0], 12), 2)]).zfill(32)
        tt1 = bin(int(SM3.ff(j, abcdefgh[0], abcdefgh[1], abcdefgh[2]), 2) + int(abcdefgh[3], 2) + int(ss2, 2) +
                  int(self.W_[j], 2))[2:].zfill(32)[-32:]
        tt2 = bin(int(SM3.gg(j, abcdefgh[4], abcdefgh[5], abcdefgh[6]), 2) + int(abcdefgh[7], 2) + int(ss1, 2) +
                  int(self.W[j], 2))[2:].zfill(32)[-32:]
        abcdefgh[3] = abcdefgh[2]
        abcdefgh[2] = SM3.shift_to_left(abcdefgh[1], 9)
        abcdefgh[1] = abcdefgh[0]
        abcdefgh[0] = tt1
        abcdefgh[7] = abcdefgh[6]
        abcdefgh[6] = SM3.shift_to_left(abcdefgh[5], 19)
        abcdefgh[5] = abcdefgh[4]
        abcdefgh[4] = SM3.p0(tt2)
        result = abcdefgh[0] + abcdefgh[1] + abcdefgh[2] + abcdefgh[3] + \
            abcdefgh[4] + abcdefgh[5] + abcdefgh[6] + abcdefgh[7]
        return result

    def hash(self):
        sm3 = None
        # 1. 填充
        l = len(self.bin_string)
        k = 0
        while (l+1+k) % 512 != 448:
            k += 1
        self.bin_string += '1' + '0' * k + bin(l)[2:].zfill(64)

        # 2. 迭代
        n = (l+1+k+64) // 512
        for i in range(n):
            self.B.append(self.bin_string[i*512:i*512+512])
        # T
        for j in range(64):
            self.T[j] = bin(int(self.T[j], 16))[2:].zfill(32)
        # 计算 W 和 W‘
        for i in range(n):
            # W
            for j in range(68):
                if 0 <= j <= 15:
                    self.W[j] = self.B[i][j*32:j*32+32]
                else:
                    op1 = SM3.p1(SM3.x_o_r([int(self.W[j-16], 2), int(self.W[j-9], 2),
                                            int(SM3.shift_to_left(self.W[j-3], 15), 2)]).zfill(32))
                    op2 = SM3.shift_to_left(self.W[j-13], 7)
                    op3 = self.W[j-6]
                    op4 = SM3.x_o_r([int(op1, 2), int(op2, 2), int(op3, 2)]).zfill(32)
                    self.W[j] = op4
            # W’
            for j in range(64):
                op1 = SM3.x_o_r([int(self.W[j], 2), int(self.W[j+4], 2)]).zfill(32)
                self.W_[j] = op1
            # 64轮迭代
            v = bin(int(self.IV, 16))[2:].zfill(256)
            for j in range(64):
                v = SM3.cf(self, j, v, self.B)
            hex_string = hex(int(v, 2))[2:].zfill(64)
            sm3 = hex(int(hex_string, 16) ^ int(self.IV, 16))[2:].zfill(64)
            self.IV = sm3
        return sm3


test1 = SM3('616263').hash()
print(test1)
test2 = SM3('61626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364').hash()
print(test2)

  • 13
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是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算法的相关文献。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值