python SM3密码杂凑算法

1.范围

    本文本规定了SM3密码杂凑算法的计算方法和计算步骤,并给出了运算示例。

    本文本适用于商用密码应用中的数字签名和验证、消息认证码的生成与验证以及随机数的生成,可满足多种密码应用的安全需求。同时,本文本还可为安全产品生产商提供产品和技术的标准定位以及标准化的参考,提高安全产品的可信性与互操作性。

2.术语和定义


2.1 比特串 bit string

    由0和1组成的的二进制数字序列

2.2 大端 bigf-endian

    数据在内存中的一种表示格式,规定左边为高有效位,右边为低有效位。数的高阶字节放在存储器的低地址,数的低阶字节放在存储器的高地址。

2.3 消息 message

    任意有限长度的比特串。本文文本中消息作为杂凑算法的输入数据。

2.4 杂凑值 hash value

    杂凑算法作用于消息后输出的特定长度的比特串,本文本中的杂凑值的长度为256比特。

2.5 字 word

    长度为32的比特串。


3.符号

    下列符号适用于本文本。

    ABCDEFGH:8个字寄存器或它们的值的串联

    B(i):第i个消息分组

    CF:压缩函数

    FFj:布尔函数,随j的变化取不同的表达式

    GGj:布尔函数,随j的变化取不同的表达式

    IV:初始值,用于确定压缩函数寄存器的初态

    P0:压缩函数中的置换函数

    P1:消息扩展中的置换函数

    Tj:常量,随j的变化取不同的值

    m:消息

    m′:填充后的消息

    mod:模运算

    ^:32比特与运算

    ⊕:32比特异或运算

    ¬:32比特非运算

    +:mod232算术加运算

    ≪ k:循环左移k比特运算

    ←:左向赋值运算符


4.常数与函数


4.1 术语和定义

    IV =7380166f 4914b2b9 172442d7 da8a0600 a96f30bc 163138aa e38dee4d b0fb0e4e

4.2 常量

Tj = {79cc4519 0 ≤ j ≤ 157a879d8a 16 ≤ j ≤ 63

4.3 布尔函数

F Fj (X, Y, Z)= { X ⊕ Y ⊕ Z 0 ≤ j ≤ 15(X ∧ Y ) ∨ (X ∧ Z) ∨ (Y ∧ Z ) 16 ≤ j ≤ 63GGj (X, Y, Z) = { X ⊕ Y ⊕ Z 0 ≤ j ≤ 15(X ∧ Y ) ∨ ( ¬X∧ Z) 16 ≤ j ≤ 63式中X,Y,Z 为字。

4.4 置换函数

在这里插入图片描述

5 算法描述


5.1 概述

    对长度为l(l < 264) 比特的消息m,SM3杂凑算法经过填充和迭代压缩,生成杂凑值,杂凑值长度为256比特。

5.2 填充

    假设消息m 的长度为 l 比特。首先将比特“1”添加到消息的末尾,再添加k 个“0”,k是满足l + 1 + k ≡ 448mod512 的最小的非负整数。然后再添加一个64位比特串,该比特串是长度l的二进制表示。填充后的消息m′ 的比特长度为512的倍数。

    例如:对消息01100001 01100010 01100011,其长度l=24,经填充得到比特串:
在这里插入图片描述

5.3 迭代压缩

5.3.1 迭代过程

    将填充后的消息m′按512比特进行分组:m′ = B(0)B(1)· · · B(n-1)

    其中n=(l+k+65)/512。 对m′按下列方式迭代:

    FOR i=0 TO n-1

        V(i+1-1) = CF(V (i), B(i))

    ENDFOR

    其中CF是压缩函数,V(0)为256比特初始值IV,B(i)为填充后的消息分组,迭代压缩的结果
为V(n)

5.3.2 消息扩展

    将消息分组B(i)按以下方法扩展生成132个字W0, W1, · · · , W67, W′0
, W′1, · · · , W′63,用于压缩函数CF:

    a)将消息分组B(i)划分为16个字W0, W1, · · · , W15

    b)FOR j=16 TO 67

        Wj ← P1(Wj-16 ⊕ Wj-9 ⊕ (Wj-3≪ 15)) ⊕ (Wj-13 ≪ 7) ⊕ Wj-6

        ENDFOR

    c)FOR j=0 TO 63

        Wj′ = Wj ⊕ Wj+4

    ENDFOR

5.3.3 压缩函数

    令A,B,C,D,E,F,G,H为字寄存器,SS1,SS2,TT1,TT2为中间变量,压缩函数V i+1 = CF(V (i), B(i)), 0 ≤ i ≤ n-1。计算过程描述如下:

    ABCDEFGH ← V (i)

    FOR j=0 TO 63

        SS1 ← ((A ≪ 12) + E + (Tj ≪ j)) ≪ 7

        SS2 ← SS1 ⊕ (A ≪ 12)

        TT1 ← FFj (A, B, C) + D + SS2 + Wj

        TT2 ← GGj (E, F, G) + H + SS1 + Wj

        D ← C

        C ← B ≪ 9

        B ← A

        A ← TT1

        H ← G

        G ← F ≪ 19

        F ← E E ← P0(TT2)

    ENDFOR

    V (i+1) ← ABCDEFGH ⊕ V (i)

    其中,字的存储为大端(big-endian)格式。

5.4 杂凑值

    ABCDEFGH ← V (n)

    输出256比特的杂凑值y = ABCDEFGH。



python 源码


IV = [
    1937774191, 1226093241, 388252375, 3666478592,
    2842636476, 372324522, 3817729613, 2969243214,
]

T_j = [
    2043430169, 2043430169, 2043430169, 2043430169, 2043430169, 2043430169,
    2043430169, 2043430169, 2043430169, 2043430169, 2043430169, 2043430169,
    2043430169, 2043430169, 2043430169, 2043430169, 2055708042, 2055708042,
    2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
    2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
    2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
    2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
    2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
    2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
    2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
    2055708042, 2055708042, 2055708042, 2055708042
]

rotl = lambda x, n:((x << n) & 0xffffffff) | ((x >> (32 - n)) & 0xffffffff)

def sm3_ff_j(x, y, z, j):
    if 0 <= j and j < 16:
        ret = x ^ y ^ z
    elif 16 <= j and j < 64:
        ret = (x & y) | (x & z) | (y & z)
    return ret

def sm3_gg_j(x, y, z, j):
    if 0 <= j and j < 16:
        ret = x ^ y ^ z
    elif 16 <= j and j < 64:
        #ret = (X | Y) & ((2 ** 32 - 1 - X) | Z)
        ret = (x & y) | ((~ x) & z)
    return ret

def sm3_p_0(x):
    return x ^ (rotl(x, 9 % 32)) ^ (rotl(x, 17 % 32))

def sm3_p_1(x):
    return x ^ (rotl(x, 15 % 32)) ^ (rotl(x, 23 % 32))

def sm3_cf(v_i, b_i):
    w = []
    for i in range(16):
        weight = 0x1000000
        data = 0
        for k in range(i*4,(i+1)*4):
            data = data + b_i[k]*weight
            weight = int(weight/0x100)
        w.append(data)

    for j in range(16, 68):
        w.append(0)
        w[j] = sm3_p_1(w[j-16] ^ w[j-9] ^ (rotl(w[j-3], 15 % 32))) ^ (rotl(w[j-13], 7 % 32)) ^ w[j-6]
        str1 = "%08x" % w[j]
    w_1 = []
    for j in range(0, 64):
        w_1.append(0)
        w_1[j] = w[j] ^ w[j+4]
        str1 = "%08x" % w_1[j]

    a, b, c, d, e, f, g, h = v_i

    for j in range(0, 64):
        ss_1 = rotl(
            ((rotl(a, 12 % 32)) +
            e +
            (rotl(T_j[j], j % 32))) & 0xffffffff, 7 % 32
        )
        ss_2 = ss_1 ^ (rotl(a, 12 % 32))
        tt_1 = (sm3_ff_j(a, b, c, j) + d + ss_2 + w_1[j]) & 0xffffffff
        tt_2 = (sm3_gg_j(e, f, g, j) + h + ss_1 + w[j]) & 0xffffffff
        d = c
        c = rotl(b, 9 % 32)
        b = a
        a = tt_1
        h = g
        g = rotl(f, 19 % 32)
        f = e
        e = sm3_p_0(tt_2)

        a, b, c, d, e, f, g, h = map(
            lambda x:x & 0xFFFFFFFF ,[a, b, c, d, e, f, g, h])

    v_j = [a, b, c, d, e, f, g, h]
    return [v_j[i] ^ v_i[i] for i in range(8)]

def sm3_hash(msg):
    # print(msg)
    len1 = len(msg)
    reserve1 = len1 % 64
    msg.append(0x80)
    reserve1 = reserve1 + 1
    # 56-64, add 64 byte
    range_end = 56
    if reserve1 > range_end:
        range_end = range_end + 64

    for i in range(reserve1, range_end):
        msg.append(0x00)

    bit_length = (len1) * 8
    bit_length_str = [bit_length % 0x100]
    for i in range(7):
        bit_length = int(bit_length / 0x100)
        bit_length_str.append(bit_length % 0x100)
    for i in range(8):
        msg.append(bit_length_str[7-i])

    group_count = round(len(msg) / 64)

    B = []
    for i in range(0, group_count):
        B.append(msg[i*64:(i+1)*64])

    V = []
    V.append(IV)
    for i in range(0, group_count):
        V.append(sm3_cf(V[i], B[i]))

    y = V[i+1]
    result = ""
    for i in y:
        result = '%s%08x' % (result, i)
    return result




bytes_to_list = lambda data: [i for i in data]

strs = "20210201173824975258"
str_b = bytes(strs, encoding='utf-8')
result = sm3_hash(bytes_to_list(str_b))
print(result) #50f03b05d10fa07f1169aff1d1e119ae3169107035b1abd24f76009ee05a8e2c

直接安装gmssl模块

from gmssl import sm3, func
strs = "20210201173824975258"
str_b = bytes(strs, encoding='utf-8')
result = sm3.sm3_hash(func.bytes_to_list(str_b))
print(result)  #50f03b05d10fa07f1169aff1d1e119ae3169107035b1abd24f76009ee05a8e2c
  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值