• python实现sm3加密算法


    sm3加密算法(即:sm3密码杂凑算法)是由国家密码管理局发布的,目前金融相关公司中对信息进行不可逆加密时,普遍采用该算法。

    该算法主要经过以下几个步骤(摘自参考1):

    1) 消息填充

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

    2)消息分组

        将填充后的消息m' 按照512比特进行分组m' = B^1B^2...B^{n-1}

        其中n=(l+k+65)/512

    3)消息扩展

        将消息分组B(i)按以下方法扩展生成132个字W_0,W_1,...,W_{67}, W'_0,W'_1,...,W'_{63},用于压缩函 数CF。详细方法请参考官方文档

    4)压缩函数CF

        详细方法请参考官方文档

    5)迭代压缩

        将分组后的消息m'按下列方式迭代:

        FOR i=0 TO n-1

            V^{i+1} = CF(V^i, B^i)

        END FOR

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

    (官方文档一定要看,看完后对该算法就有个比较清晰的认识了)

    完整代码如下:

    1. # -*- coding:utf-8 -*-
    2. """
    3. :author: liyebei
    4. :date: 2022-08-06
    5. :description: SM3加密算法。 适用于python2.7+, python3.5+(用python3时暂不支持对中文的加密)
    6. """
    7. # 初始值
    8. iv = 0x7380166f4914b2b9172442d7da8a0600a96f30bc163138aae38dee4db0fb0e4e
    9. MAX = 2 ** 32
    10. def str2bin(msg):
    11. """
    12. 字符串转比特串
    13. :param msg: 字符串
    14. :return: 转换之后的比特串
    15. """
    16. l = len(msg)
    17. s_dec = 0
    18. for m in msg:
    19. s_dec = s_dec << 8
    20. s_dec += ord(m)
    21. msg_bin = bin(s_dec)[2:].zfill(l * 8)
    22. return msg_bin
    23. def int2bin(a, k):
    24. """
    25. 将整数转化为比特串
    26. :param a: 待转化的整数
    27. :param k: 比特串的长度
    28. :return: 转化后长度为k的比特串
    29. """
    30. return bin(a)[2:].zfill(k)
    31. def int2hex(a, k):
    32. """
    33. 整数转化为16进制的字符串,前补0补齐k位数
    34. :param a: 整数
    35. :param k: 补齐后的字符串长度
    36. :return: 转化后的16进制形式字符串
    37. """
    38. return hex(a)[2:].zfill(k)
    39. def bin2hex(a, k):
    40. """
    41. 比特串转化为16进制的字符串,前补0补齐k位数
    42. :param a: 待转化的比特串
    43. :param k: 补齐后的字符串长度
    44. :return: 长度为k的16进制字符串
    45. """
    46. return hex(int(a, 2))[2:].zfill(k)
    47. def msg_fill(msg_bin):
    48. """
    49. 对消息进行填充。填充后的消息满足:(l+1+k) mod 512 = 448 k取最小值
    50. :param msg_bin: 比特串形式的消息
    51. :return: 填充后的消息(比特串形式)
    52. """
    53. l = len(msg_bin)
    54. k = 448 - (l + 1) % 512
    55. if k < 0:
    56. k += 512
    57. l_bin = int2bin(l, 64)
    58. msg_filled = msg_bin + '1' + '0' * k + l_bin
    59. return msg_filled
    60. def iteration_func(msg):
    61. """
    62. 迭代压缩
    63. :param msg: 填充后的比特串消息
    64. :return: 迭代压缩后的消息,长度为64的字符串
    65. """
    66. # 将填充后的消息按512比特进行分组
    67. n = len(msg) // 512
    68. b = []
    69. for i in range(n):
    70. b.append(msg[512 * i:512 * (i + 1)])
    71. # 对消息进行迭代压缩
    72. v = [int2bin(iv, 256)]
    73. for i in range(n):
    74. v.append(cf(v[i], b[i]))
    75. return bin2hex(v[n], 64)
    76. def msg_extension(bi):
    77. """
    78. 消息扩展, 将消息分组bi扩展生成132个字W0, W1, · · · , W67, W0', W1', · · · , W63',用于压缩函数CF
    79. :param bi: 填充后的消息分组,长度为512的比特串
    80. :return: w, w1 扩展后的消息,w为68字的list, w1为64字的list。字以整数存储
    81. """
    82. # 将消息分组Bi划分为16个字W0, W1, · · · , W15
    83. w = []
    84. for j in range(16):
    85. w.append(int(bi[j * 32:(j + 1) * 32], 2))
    86. for j in range(16, 68):
    87. w_j = p1(w[j - 16] ^ w[j - 9] ^ rotate_left(w[j - 3], 15)) ^ rotate_left(w[j - 13], 7) ^ w[j - 6]
    88. w.append(w_j)
    89. w1 = []
    90. for j in range(64):
    91. w1.append(w[j] ^ w[j + 4])
    92. return w, w1
    93. def cf(vi, bi):
    94. """
    95. 压缩函数
    96. :param vi: 比特串(256位)
    97. :param bi: 填充后的消息分组(512位比特串)
    98. :return: 压缩后的比特串(256位)
    99. """
    100. # 对bi进行消息扩展
    101. w, w1 = msg_extension(bi)
    102. # 将vi拆分为 a~h 8个字
    103. t = []
    104. for i in range(8):
    105. t.append(int(vi[i * 32:(i + 1) * 32], 2))
    106. a, b, c, d, e, f, g, h = t
    107. for j in range(64):
    108. ss1 = rotate_left((rotate_left(a, 12) + e + rotate_left(t_j(j), j)) % MAX, 7)
    109. ss2 = ss1 ^ rotate_left(a, 12)
    110. tt1 = (ff(a, b, c, j) + d + ss2 + w1[j]) % MAX
    111. tt2 = (gg(e, f, g, j) + h + ss1 + w[j]) % MAX
    112. d = c
    113. c = rotate_left(b, 9)
    114. b = a
    115. a = tt1
    116. h = g
    117. g = rotate_left(f, 19)
    118. f = e
    119. e = p0(tt2)
    120. vi_1 = int2bin(a, 32) + int2bin(b, 32) + int2bin(c, 32) + int2bin(d, 32) \
    121. + int2bin(e, 32) + int2bin(f, 32) + int2bin(g, 32) + int2bin(h, 32)
    122. vi_1 = int(vi_1, 2) ^ int(vi, 2)
    123. return int2bin(vi_1, 256)
    124. def rotate_left(a, k):
    125. """
    126. (字)循环左移k比特运算
    127. :param a: 待按位左移的比特串
    128. :param k: 左移位数
    129. :return:
    130. """
    131. k = k % 32
    132. return ((a << k) & 0xFFFFFFFF) | ((a & 0xFFFFFFFF) >> (32 - k))
    133. def p0(x):
    134. """
    135. 置换函数P0
    136. :param x: 待置换的消息(字)
    137. :return: 置换后的消息(字)
    138. """
    139. return x ^ rotate_left(x, 9) ^ rotate_left(x, 17)
    140. def p1(x):
    141. """
    142. 置换函数P1
    143. :param x: 待置换的消息(字)
    144. :return: 置换后的消息(字)
    145. """
    146. return x ^ rotate_left(x, 15) ^ rotate_left(x, 23)
    147. def t_j(j):
    148. """
    149. 常量
    150. """
    151. if j <= 15:
    152. return 0x79cc4519
    153. else:
    154. return 0x7a879d8a
    155. def ff(x, y, z, j):
    156. """
    157. 布尔函数ff
    158. """
    159. if j <= 15:
    160. return x ^ y ^ z
    161. else:
    162. return (x & y) | (x & z) | (y & z)
    163. def gg(x, y, z, j):
    164. """
    165. 布尔函数gg
    166. """
    167. if j <= 15:
    168. return x ^ y ^ z
    169. else:
    170. return (x & y) | ((x ^ 0xFFFFFFFF) & z)
    171. def sm3(msg):
    172. """
    173. sm3加密主函数
    174. :param msg: 待加密的字符串
    175. :return: sm3加密后的字符串
    176. """
    177. # 字符串转化为比特串
    178. s_bin = str2bin(msg)
    179. # 对消息进行填充
    180. s_fill = msg_fill(s_bin)
    181. # 对填充后的消息进行迭代压缩
    182. s_sm3 = iteration_func(s_fill)
    183. # 对于python2需要删除因长整型而引入的末尾的L字符,python3不存在该问题
    184. return s_sm3.upper().replace("L", "")
    185. if __name__ == "__main__":
    186. s1 = 'abc'
    187. s1_sm3 = sm3(s1)
    188. print("{} ==> {}".format(s1, s1_sm3))
    189. s2 = 'hello'
    190. s2_sm3 = sm3(s2)
    191. print("{} ==> {}".format(s2, s2_sm3))

    代码执行结果:

    abc ==> 66C7F0F462EEEDD9D1F2D46BDC10E4E24167C4875CF2F7A2297DA02B8F4BA8E0
    hello ==> BECBBFAAE6548B8BF0CFCAD5A27183CD1BE6093B1CCECCC303D9C61D0A645268

    参考1:国家密码管理局发布的《SM3密码杂凑算法》 

  • 相关阅读:
    关于什么是框架
    [C++数据结构](23)哈希:位图,布隆过滤器,哈希切割
    大数据-数据分析初步学习,待补充
    [hive]维度模型分类:星型模型,雪花模型,星座模型|范式|数仓分层|用户纬度拉链表|维度建模
    Element系列之 keep-alive 中使用 show-overflow-tooltip 切换路由 tooltip 不消失的解决办法
    jersey跨域文件上传
    用tkinter+selenium做一个CSDN热榜爬虫
    [2023年]-hadoop面试真题(三)
    【USRP】软件无线电基础篇:长波、中波、短波
    Halcon中涉及的数字图像十大理论知识
  • 原文地址:https://blog.csdn.net/liyebei/article/details/126207132