Python教程

【Python实现】SM3密码杂凑算法

本文主要是介绍【Python实现】SM3密码杂凑算法,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

前言

这是我大三上学期的一个作品。然后为了能够显示中间过程,用面向过程的思想编写。

  • 注:强烈建议用 jupyter 运行代码
  • n 代表运行顺序
    • In [n]: 代表第 n 步运行
    • Out [n]: 代表第 n 步运行对应的输入
    • In [ ]: 代表不运行

SM3密码杂凑算法.pdf下载

国家密码管理局关于发布《SM3密码杂凑算法》公告
发布日期:2010-12-17
来源:国家密码管理局

准备

统一数据结构(以65535为例)

In [1]:

import numpy as np

32位二进制(列表形式)

In [2]:

# 示例:array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=np.uint8)

# 十进制 转 32位二进制
def Dec_to_Bin(Dec):
    Dec %= 2**32
    return np.array([Dec >> tmp & 1 for tmp in range(32)][::-1], dtype = np.uint8)

# 十六进制 转 32位二进制
def Hex_to_Bin(Hex):
    return Dec_to_Bin(eval('0x' + Hex))

十进制

In [3]:

# 示例:65535

# 二进制 转 十进制
def Bin_to_Dec(Bin):
    Dec = 0
    for i in range(len(Bin)):
        Dec += Bin[-i-1] * 2 ** i
    return Dec

# 十六进制 转 十进制
def Hex_to_Dec(Hex):
    return eval('0x' + Hex)

8位十六进制(字符串形式)

In [4]:

# 示例:'0000ffff'

# 32位二进制 转 8位十六进制
def Bin_to_Hex(Bin):
    Hex = ''
    for i in range(len(Bin)//4):
        tmp = hex(Bin_to_Dec(Bin[4 * i : 4 * (i + 1)]))[-1]
        Hex += str(tmp)
    return Hex

# 十进制 转 8位十六进制
def Dec_to_Hex(Dec):
    Dec %= 2**32
    Hex = ''
    for tmp1 in [hex(Dec >> (tmp2 * 4) & 0xf)[-1] for tmp2 in range(8)][::-1]:
        Hex += str(tmp1)
    return Hex

64位十六进制(字符串形式)

In [5]:

# 十进制 转 64位十六进制
def Dec_to_Hex_64(Dec):
    Hex = ''
    for tmp1 in [hex((Dec) >> (tmp2 * 4) & 0xf)[-1] for tmp2 in range(64)][::-1]:
        Hex += str(tmp1)
    return Hex

定义 循环左移 和 按位取反 函数

In [6]:

# 循环左移
def cycle_left(X, n, dtype):
    if dtype == 'Bin':
        n = n % 32
        return Bin_to_Dec(np.append(X[n:], X[:n]))
    elif dtype == 'Dec':
        return cycle_left(Dec_to_Bin(X), n, 'Bin')
    elif dtype == 'Hex':
        return cycle_left(Hex_to_Bin(X), n, 'Bin')
    else:
        raise TypeError("二进制请输入np_bin和Bin,十进制请输入num和Dec,十六进制请输入str和Hex")

In [7]:

# 按位取反
def invert(X, dtype):
    if dtype == 'Bin':
        for i in range(len(X)):
            if X[i] == 0:
                X[i] = 1
            else:
                X[i] = 0
        return Bin_to_Dec(X)
    elif dtype == 'Dec':
        return invert(Dec_to_Bin(X), 'Bin')
    elif dtype == 'Hex':
        return invert(Hex_to_Bin(X), 'Bin')
    else:
        raise TypeError("二进制请输入np_bin和Bin,十进制请输入num和Dec,十六进制请输入str和Hex")

常数与函数

In [8]:

# 初始值
IV = '7380166f4914b2b9172442d7da8a0600a96f30bc163138aae38dee4db0fb0e4e'

In [9]:

# 常量
def T(j):
    if 0 <= j <= 15:
        return 0x79cc4519
    elif 16 <= j <= 63:
        return 0x7a879d8a

In [10]:

# 布尔函数

def FF(X, Y, Z, j):
    
    X %= 2**32
    Y %= 2**32
    Z %= 2**32
    
    if 0 <= j <= 15:
        return X ^ Y ^ Z
    elif 16 <= j <= 63:
        return (X & Y) | (X & Z) | (Y & Z)

def GG(X, Y, Z, j):
    
    X %= 2**32
    Y %= 2**32
    Z %= 2**32
    
    if 0 <= j <= 15:
        return X ^ Y ^ Z
    elif 16 <= j <= 63:
        return (X & Y) | (invert(X, 'Dec') & Z)

In [11]:

# 置换函数

def P0(X):
    X %= 2**32
    return X ^ cycle_left(X, 9, 'Dec') ^ cycle_left(X, 17, 'Dec')

def P1(X):
    X %= 2**32
    return X ^ cycle_left(X, 15, 'Dec') ^ cycle_left(X, 23, 'Dec')

算法实现

填充

In [12]:

# 消息m
m = b'abc'
# m = b'abcd' * 16

In [13]:

# 消息 -> ASCII码 -> 二进制
ASCII = np.frombuffer(m, dtype = np.uint8)
Bit = np.unpackbits(ASCII)

In [14]:

# 假设消息 m 的长度为 l 比特
l = len(Bit)
print("原始消息长度为 %d 比特" % l)

Out [14]:

原始消息长度为 24 比特

In [15]:

# 在消息的末尾添加一个1比特的数值"1",N_512_Bit 代表 512整数倍比特
ONE = np.ones(1, dtype = np.uint8)
N_512_Bit = np.append(Bit, ONE)

In [16]:

# N 为512比特长度的倍数
# k 为需要添加的0的个数,满足 l + 1 + k = 448mod512
N = 1
while True:
    if l + 1 + 64 <= 512 * N:
        k = 512 * N - l - 1 - 64
        break
    N += 1

In [17]:

# 添加消息长度(不包括最后一个分组)
print("需要添加 %d 个'0'" % k)
ZEROS = np.zeros(k, dtype = np.uint8)
N_512_Bit = np.append(N_512_Bit, ZEROS)

Out [17]:

需要添加 423 个'0'

In [18]:

# 保存原始消息的长度到最后一个分组的最后64比特
last_64_bit = [l >> d & 1 for d in range(64)][::-1]
last_64_bit = np.array(last_64_bit, dtype = np.uint8)
N_512_Bit = np.append(N_512_Bit, last_64_bit)

In [19]:

# 填充后的结果展示(二进制表示)
for i in range(len(N_512_Bit)):
    print(N_512_Bit[i], end = '')
    if (i + 1) % 64 == 0:
        print()
    elif (i + 1) % 8 == 0:
        print(end = ' ')
    else:
        pass

Out [19]:

01100001 01100010 01100011 10000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00011000

In [20]:

# 填充后的结果展示(十六进制表示)
N_128_hex = Bin_to_Hex(N_512_Bit)
for i in range(len(N_128_hex)):
    print(N_128_hex[i], end = '')
    if (i + 1) % 64 == 0:
        print()
    elif (i + 1) % 8 == 0:
        print(end = ' ')
    else:
        pass

Out [20]:

61626380 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000018

迭代压缩

迭代过程

In [22]:

# 按512比特进行分组
def split_group(N_512_Bit, N):
    print("有 %d 个组" % N)
    Group = {}
    for i in range(N):
        Group["Group" + str(i)] = message_extension(N_512_Bit[512 * i : 512 * (i + 1)])
    return Group

In [23]:

# 将填充后的消息 m' 按512比特进行分组(程序中用 m_ 代替 m')
Group = split_group(N_512_Bit, N)

Out [23]:

有 1 个组

In [26]:

V_i_1 = V_i = IV
for n in range(N):
    B_i = Group['Group' + str(n)]
    V_i = V_i_1
    
    # V(i + 1) = CF(V(i), B(i))
    V_i_1 = CF(V_i, B_i)

Out [26]:

 j    A        B        C        D        E        F        G        H    
   7380166f 4914b2b9 172442d7 da8a0600 a96f30bc 163138aa e38dee4d b0fb0e4e
 0 b9edc12b 7380166f 29657292 172442d7 b2ad29f4 a96f30bc c550b189 e38dee4d
 1 ea52428c b9edc12b 002cdee7 29657292 ac353a23 b2ad29f4 85e54b79 c550b189
 2 609f2850 ea52428c db825773 002cdee7 d33ad5fb ac353a23 4fa59569 85e54b79
 3 35037e59 609f2850 a48519d4 db825773 b8204b5f d33ad5fb d11d61a9 4fa59569
 4 1f995766 35037e59 3e50a0c1 a48519d4 8ad212ea b8204b5f afde99d6 d11d61a9
 5 374a0ca7 1f995766 06fcb26a 3e50a0c1 acf0f639 8ad212ea 5afdc102 afde99d6
 6 33130100 374a0ca7 32aecc3f 06fcb26a 3391ec8a acf0f639 97545690 5afdc102
 7 1022ac97 33130100 94194e6e 32aecc3f 367250a1 3391ec8a b1cd6787 97545690
 8 d47caf4c 1022ac97 26020066 94194e6e 6ad473a4 367250a1 64519c8f b1cd6787
 9 59c2744b d47caf4c 45592e20 26020066 c6a3ceae 6ad473a4 8509b392 64519c8f
10 481ba2a0 59c2744b f95e99a8 45592e20 02afb727 c6a3ceae 9d2356a3 8509b392
11 694a3d09 481ba2a0 84e896b3 f95e99a8 9dd1b58c 02afb727 7576351e 9d2356a3
12 89cbcd58 694a3d09 37454090 84e896b3 6370db62 9dd1b58c b938157d 7576351e
13 24c95abc 89cbcd58 947a12d2 37454090 1a4a2554 6370db62 ac64ee8d b938157d
14 7c529778 24c95abc 979ab113 947a12d2 3ee95933 1a4a2554 db131b86 ac64ee8d
15 34d1691e 7c529778 92b57849 979ab113 61f99646 3ee95933 2aa0d251 db131b86
16 796afab1 34d1691e a52ef0f8 92b57849 067550f5 61f99646 c999f74a 2aa0d251
17 7d27cc0e 796afab1 a2d23c69 a52ef0f8 b3c8669b 067550f5 b2330fcc c999f74a
18 d7820ad1 7d27cc0e d5f562f2 a2d23c69 575c37d8 b3c8669b 87a833aa b2330fcc
19 f84fd372 d7820ad1 4f981cfa d5f562f2 a5dceaf1 575c37d8 34dd9e43 87a833aa
20 02c57896 f84fd372 0415a3af 4f981cfa 74576681 a5dceaf1 bec2bae1 34dd9e43
21 4d0c2fcd 02c57896 9fa6e5f0 0415a3af 576f1d09 74576681 578d2ee7 bec2bae1
22 eeeec41a 4d0c2fcd 8af12c05 9fa6e5f0 b5523911 576f1d09 340ba2bb 578d2ee7
23 f368da78 eeeec41a 185f9a9a 8af12c05 6a879032 b5523911 e84abb78 340ba2bb
24 15ce1286 f368da78 dd8835dd 185f9a9a 62063354 6a879032 c88daa91 e84abb78
25 c3fd31c2 15ce1286 d1b4f1e6 dd8835dd 4db58f43 62063354 8193543c c88daa91
26 6243be5e c3fd31c2 9c250c2b d1b4f1e6 131152fe 4db58f43 9aa31031 8193543c
27 a549beaa 6243be5e fa638587 9c250c2b cf65e309 131152fe 7a1a6dac 9aa31031
28 e11eb847 a549beaa 877cbcc4 fa638587 e5b64e96 cf65e309 97f0988a 7a1a6dac
29 ff9bac9d e11eb847 937d554a 877cbcc4 9811b46d e5b64e96 184e7b2f 97f0988a
30 a5a4a2b3 ff9bac9d 3d708fc2 937d554a e92df4ea 9811b46d 74b72db2 184e7b2f
31 89a13e59 a5a4a2b3 37593bff 3d708fc2 0a1ff572 e92df4ea a36cc08d 74b72db2
32 3720bd4e 89a13e59 4945674b 37593bff cf7d1683 0a1ff572 a757496f a36cc08d
33 9ccd089c 3720bd4e 427cb313 4945674b da8c835f cf7d1683 ab9050ff a757496f
34 c7a0744d 9ccd089c 417a9c6e 427cb313 0958ff1b da8c835f b41e7be8 ab9050ff
35 d955c3ed c7a0744d 9a113939 417a9c6e c533f0ff 0958ff1b 1afed464 b41e7be8
36 e142d72b d955c3ed 40e89b8f 9a113939 d4509586 c533f0ff f8d84ac7 1afed464
37 e7250598 e142d72b ab87dbb2 40e89b8f c7f93fd3 d4509586 87fe299f f8d84ac7
38 2f13c4ad e7250598 85ae57c2 ab87dbb2 1a6cabc9 c7f93fd3 ac36a284 87fe299f
39 19f363f9 2f13c4ad 4a0b31ce 85ae57c2 c302badb 1a6cabc9 fe9e3fc9 ac36a284
40 55e1dde2 19f363f9 27895a5e 4a0b31ce 459daccf c302badb 5e48d365 fe9e3fc9
41 d4f4efe3 55e1dde2 e6c7f233 27895a5e 5cfba85a 459daccf d6de1815 5e48d365
42 48dcbc62 d4f4efe3 c3bbc4ab e6c7f233 6f49c7bb 5cfba85a 667a2ced d6de1815
43 8237b8a0 48dcbc62 e9dfc7a9 c3bbc4ab d89d2711 6f49c7bb 42d2e7dd 667a2ced
44 d8685939 8237b8a0 b978c491 e9dfc7a9 8ee87df5 d89d2711 3ddb7a4e 42d2e7dd
45 d2090a86 d8685939 6f714104 b978c491 2e533625 8ee87df5 388ec4e9 3ddb7a4e
46 e51076b3 d2090a86 d0b273b0 6f714104 d9f89e61 2e533625 efac7743 388ec4e9
47 47c5be50 e51076b3 12150da4 d0b273b0 3567734e d9f89e61 b1297299 efac7743
48 abddbdc8 47c5be50 20ed67ca 12150da4 3dfcdd11 3567734e f30ecfc4 b1297299
49 bd708003 abddbdc8 8b7ca08f 20ed67ca 93494bc0 3dfcdd11 9a71ab3b f30ecfc4
50 15e2f5d3 bd708003 bb7b9157 8b7ca08f c3956c3f 93494bc0 e889efe6 9a71ab3b
51 13826486 15e2f5d3 e100077a bb7b9157 cd09a51c c3956c3f 5e049a4a e889efe6
52 4a00ed2f 13826486 c5eba62b e100077a 0741f675 cd09a51c 61fe1cab 5e049a4a
53 f4412e82 4a00ed2f 04c90c27 c5eba62b 7429807c 0741f675 28e6684d 61fe1cab
54 549db4b7 f4412e82 01da5e94 04c90c27 f6bc15ed 7429807c b3a83a0f 28e6684d
55 22a79585 549db4b7 825d05e8 01da5e94 9d4db19a f6bc15ed 03e3a14c b3a83a0f
56 30245b78 22a79585 3b696ea9 825d05e8 f6804c82 9d4db19a af6fb5e0 03e3a14c
57 6598314f 30245b78 4f2b0a45 3b696ea9 f522adb2 f6804c82 8cd4ea6d af6fb5e0
58 c3d629a9 6598314f 48b6f060 4f2b0a45 14fb0764 f522adb2 6417b402 8cd4ea6d
59 ddb0a26a c3d629a9 30629ecb 48b6f060 589f7d5c 14fb0764 6d97a915 6417b402
60 71034d71 ddb0a26a ac535387 30629ecb 14d5c7f6 589f7d5c 3b20a7d8 6d97a915
61 5e636b4b 71034d71 6144d5bb ac535387 09ccd95e 14d5c7f6 eae2c4fb 3b20a7d8
62 2bfa5f60 5e636b4b 069ae2e2 6144d5bb 4ac3cf08 09ccd95e 3fb0a6ae eae2c4fb
63 1547e69b 2bfa5f60 c6d696bc 069ae2e2 e808f43b 4ac3cf08 caf04e66 3fb0a6ae

消息扩展

In [21]:

def message_extension(_512_bit):
    
    W = {}
    
    # W0 ~ W67
    for j in range(68):
        
        # W0 ~ W15
        if j <= 15:
            W["W" + str(j)] = Bin_to_Dec(_512_bit[32 * j : 32 * (j + 1)])
        
        # W16 ~ W67
        elif 16 <= j <= 67:
            W_j_16 = W["W" + str(j - 16)]
            W_j_13 = W["W" + str(j - 13)]
            W_j_9  = W["W" + str(j - 9)]
            W_j_6  = W["W" + str(j - 6)]
            W_j_3  = W["W" + str(j - 3)]

            W["W" + str(j)] = P1(W_j_16 ^ W_j_9 ^ cycle_left(W_j_3, 15, 'Dec')) ^ cycle_left(W_j_13, 7, 'Dec') ^ W_j_6
    
    # W'0 ~ W'63(程序中用 W_ 代替 W')
    for j in range(64):
        W["W_" + str(j)] = W['W' + str(j)] ^ W['W' + str(j + 4)]

    return W

In [24]:

for j in range(N):
    print("W0 ~ W67")
    W = Group['Group' + str(j)]
    for i in range(68):
        print(Dec_to_Hex(W['W' + str(i)]), end=' ')
        if (i + 1) % 8 == 0:
            print()

    print("\n\n" + "W'0 ~ W'63")
    W = Group['Group' + str(j)]
    for i in range(64):
        print(Dec_to_Hex(W['W_' + str(i)]), end=' ')
        if (i + 1) % 8 == 0:
            print()
    
    print()

Out [24]:

W0 ~ W67
61626380 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000018 
9092e200 00000000 000c0606 719c70ed 00000000 8001801f 939f7da9 00000000 
2c6fa1f9 adaaef14 00000000 0001801e 9a965f89 49710048 23ce86a1 b2d12f1b 
e1dae338 f8061807 055d68be 86cfd481 1f447d83 d9023dbf 185898e0 e0061807 
050df55c cde0104c a5b9c955 a7df0184 6e46cd08 e3babdf8 70caa422 0353af50 
a92dbca1 5f33cfd2 e16f6e89 f70fe941 ca5462dc 85a90152 76af6296 c922bdb2 
68378cf5 97585344 09008723 86faee74 2ab908b0 4a64bc50 864e6e08 f07e6590 
325c8f78 accb8011 e11db9dd b99c0545 

W'0 ~ W'63
61626380 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
00000000 00000000 00000000 00000018 9092e200 00000000 000c0606 719c70f5 
9092e200 8001801f 93937baf 719c70ed 2c6fa1f9 2dab6f0b 939f7da9 0001801e 
b6f9fe70 e4dbef5c 23ce86a1 b2d0af05 7b4cbcb1 b177184f 2693ee1f 341efb9a 
fe9e9ebb 210425b8 1d05f05e 66c9cc86 1a4988df 14e22df3 bde151b5 47d91983 
6b4b3854 2e5aadb4 d5736d77 a48caed4 c76b71a9 bc89722a 91a5caab f45c4611 
6379de7d da9ace80 97c00c1f 3e2d54f3 a263ee29 12f15216 7fafe5b5 4fd853c6 
428e8445 dd3cef14 8f4ee92b 76848be4 18e587c8 e6af3c41 6753d7d5 49e260d5 

压缩函数

In [25]:

def CF(V_i, B_i):
    
    A = eval('0x' + V_i[ 0 :  8])
    B = eval('0x' + V_i[ 8 : 16])
    C = eval('0x' + V_i[16 : 24])
    D = eval('0x' + V_i[24 : 32])
    E = eval('0x' + V_i[32 : 40])
    F = eval('0x' + V_i[40 : 48])
    G = eval('0x' + V_i[48 : 56])
    H = eval('0x' + V_i[56 : 64])
    
    print(' j', '{:^9}{:^9}{:^9}{:^9}{:^9}{:^9}{:^9}{:^9}'.format('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'), sep='')
    print(
        '  ',
        Dec_to_Hex(A),
        Dec_to_Hex(B),
        Dec_to_Hex(C),
        Dec_to_Hex(D),
        Dec_to_Hex(E),
        Dec_to_Hex(F),
        Dec_to_Hex(G),
        Dec_to_Hex(H)
    )
    
    for j in range(64):
        
        SS1 = cycle_left(cycle_left(A, 12, 'Dec') + E + cycle_left(T(j), j, 'Dec'), 7, 'Dec')
        SS2 = SS1 ^ cycle_left(A, 12, 'Dec')
        TT1 = FF(A, B, C, j) + D + SS2 + B_i["W_" + str(j)]
        TT2 = GG(E, F, G, j) + H + SS1 + B_i["W" + str(j)]
        D = C
        C = cycle_left(B, 9, 'Dec')
        B = A
        A = TT1
        H = G
        G = cycle_left(F, 19, 'Dec')
        F = E
        E = P0(TT2)
        
        print(
            '{:>2}'.format(j),
            Dec_to_Hex(A),
            Dec_to_Hex(B),
            Dec_to_Hex(C),
            Dec_to_Hex(D),
            Dec_to_Hex(E),
            Dec_to_Hex(F),
            Dec_to_Hex(G),
            Dec_to_Hex(H)
        )
    
    print()
    
    new_ABCDEFGH = ''
    for each in [A, B, C, D, E, F, G, H]:
        new_ABCDEFGH += Dec_to_Hex(each)
    
    V_i_1 = Hex_to_Dec(new_ABCDEFGH) ^ Hex_to_Dec(V_i)
    
    return Dec_to_Hex_64(V_i_1)

杂凑值

In [27]:

# 'abc'
V_i_1 == '66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0'

Out [27]:

True

In [ ]:

# 'abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd'
# V_i_1 == 'debe9ff92275b8a138604889c18e5a4d6fdb70e5387e5765293dcba39c0c5732'
这篇关于【Python实现】SM3密码杂凑算法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!