SM3杂凑算法的C、python和go实现

Github

https://github.com/Tyrone-Zhao/Algorithm/tree/master/sm3

注意点

Python

1.python中的非为补码非,需要自己编写按位非
2.算法为大端运算,用python编写算法时需要在把输入数据转换成bytes后,从bytes读取大端数据,使用int.from_bytes(data, “big”)方法
3.因为是采用寄存器机制,所以在python中需要使用list类型来实现, 并且设定最大值为2 ** 32,在做加法运算时需要取余

Python代码

python SM3算法

import binascii
import sys
import pysnooper


class SM3:
    MAX = 2 ** 32
    IV = "7380166f4914b2b9172442d7da8a0600a96f30bc163138aae38dee4db0fb0e4e"

    def __init__(self, string):
        self.input = string
        self.b_input = bytes(self.input, "utf-8")
        self.hex_input = hex(int.from_bytes(self.b_input, "big"))[2:]  # 按照大端计算

    @property
    def hash(self):
        """
        获取结果Hash值
        :return: 256位16进制hash值
        """
        return self.iterationCourse(self.fill(self.hexToBin(self.hex_input)))[-1]

    def getT(self, j):
        """
        常量
        :param j:
        :return: 79cc4519 (0 <= j <= 15), 7a879d8a (16 <= j <= 63)
        """
        if 0 <= j <= 15:
            return int("79cc4519", 16)
        elif 16 <= j <= 63:
            return int("7a879d8a", 16)

    def FF(self, X, Y, Z, j):
        """
        布尔函数
        :param X: 16进制string
        :param Y: 16进制string
        :param Z: 16进制string
        :return: X ^ Y ^ Z (0 <= j <= 15), (X & Y) | (X & Z) | (Y & Z) (16 <= j <= 63)
        """
        if 0 <= j <= 15:
            return X ^ Y ^ Z
        elif 16 <= j <= 63:
            return (X & Y) | (X & Z) | (Y & Z)
        else:
            return 0

    def GG(self, X, Y, Z, j):
        """
        布尔函数
        :param X: 16进制string
        :param Y: 16进制string
        :param Z: 16进制string
        :return: X ^ Y ^ Z (0 <= j <= 15), (X & Y) | (~X & Z) (16 <= j <= 63)
        """
        if 0 <= j <= 15:
            return X ^ Y ^ Z
        elif 16 <= j <= 63:
            return (X & Y) | (self.non(X) & Z)
        else:
            return 0

    def P0(self, X):
        """
        置换函数
        :param X: 整数值
        :return: X ^ (X <<< 9) ^ (X <<< 17)
        """
        return X ^ self.leftRotate(X, 9) ^ self.leftRotate(X, 17)

    def P1(self, X):
        """
        置换函数
        :param X: 整数值
        :return: X ^ (X <<< 15) ^ (X <<< 23)
        """
        return X ^ self.leftRotate(X, 15) ^ self.leftRotate(X, 23)

    def leftRotate(self, X, k):
        """
        循环左移
        :param X: 整数值
        :param k: 位移的位数
        :param bit: 整数对应二进制的位数
        :return: 二进制左移k位的整数值
        """
        res = list(self.intToBin(X))
        for i in range(k):
            temp = res.pop(0)
            res.append(temp)
        return int("".join(res), 2)

    def fill(self, bin_string):
        """
        填充二进制消息string
        :param bin_string: 对任意消息使用self.msgToBin()得到的结果
        :return: 填充后的二进制消息m',其比特长度为512的倍数
        """
        tail = "{:064b}".format(len(bin_string))
        bin_string += "1"
        div, mod = divmod(len(bin_string), 512)
        if mod >= 448:
            bin_string += "0" * (512 - mod + 448)
        else:
            bin_string += "0" * (448 - mod)

        return bin_string + tail

    def iterationCourse(self, msg):
        """
        迭代压缩消息
        :param msg: 填充后的二进制消息m', self.fill(msg)
        :return: Hash值(杂凑值)
        """
        # 将填充消息m'按512比特进行分组
        n = len(msg) // 512
        m = [msg[i * 512:(i + 1) * 512] for i in range(n)]
        # 对m[i]进行压缩迭代, msg = self.bigLittleEndianConvert(Vi, "big")  # 小端数据转换为大端
        V = [self.IV]
        for i in range(n):
            V.append(hex(int(self.intToBin(self.CF(V[-1], m[i]), 256), 2))[2:])

        return V

    def CF(self, Vi, mi):
        """
        压缩函数
        :param Vi: 512比特16进制数据
        :param mi: 512比特二进制数据
        :return: 512比特16进制数据
        """
        # 将Vi存储到字寄存器
        msg = Vi
        A = [int(msg[i * 8: (i + 1) * 8], 16) for i in range(len(msg) // 8)]
        # 消息扩展,得到W和W'
        W1, W2 = self.informationExtend(mi)
        # 压缩消息
        for j in range(64):
            factor1 = self.leftRotate(A[0], 12)
            factor2 = self.leftRotate(self.getT(j), j % 32)
            SS1 = self.leftRotate((factor1 + A[4] + factor2) % self.MAX, 7)
            factor3 = self.leftRotate(A[0], 12)
            SS2 = SS1 ^ factor3
            TT1 = (self.FF(A[0], A[1], A[2], j) + A[3] + SS2 + W2[j]) % self.MAX
            TT2 = (self.GG(A[4], A[5], A[6], j) + A[7] + SS1 + W1[j]) % self.MAX
            A[3] = A[2]
            A[2] = self.leftRotate(A[1], 9)
            A[1] = A[0]
            A[0] = TT1
            A[7] = A[6]
            A[6] = self.leftRotate(A[5], 19)
            A[5] = A[4]
            A[4] = self.P0(TT2)
        temp = self.intToBin(A[0], 32) + self.intToBin(A[1], 32) + self.intToBin(A[2], 32) + \
               self.intToBin(A[3], 32) + self.intToBin(A[4], 32) + self.intToBin(A[5], 32) + \
               self.intToBin(A[6], 32) + self.intToBin(A[7]
  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值