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

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

1) 消息填充

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

2)消息分组

将填充后的消息m' 按照512比特进行分组

其中

3)消息扩展

将消息分组B(i)按以下方法扩展生成132个字,用于压缩函 数CF。详细方法请参考官方文档

4)压缩函数CF

详细方法请参考官方文档

5)迭代压缩

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

FOR i=0 TO n-1

END FOR

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

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

完整代码如下:

# -*- coding:utf-8 -*-"""
:author: liyebei
:date: 2022-08-06
:description: SM3加密算法。 适用于python2.7+, python3.5+(用python3时暂不支持对中文的加密)
"""# 初始值
iv = 0x7380166f4914b2b9172442d7da8a0600a96f30bc163138aae38dee4db0fb0e4e
MAX = 2 ** 32def str2bin(msg):"""字符串转比特串:param msg: 字符串:return: 转换之后的比特串"""l = len(msg)s_dec = 0for m in msg:s_dec = s_dec << 8s_dec += ord(m)msg_bin = bin(s_dec)[2:].zfill(l * 8)return msg_bindef int2bin(a, k):"""将整数转化为比特串:param a: 待转化的整数:param k: 比特串的长度:return: 转化后长度为k的比特串"""return bin(a)[2:].zfill(k)def int2hex(a, k):"""整数转化为16进制的字符串,前补0补齐k位数:param a: 整数:param k: 补齐后的字符串长度:return: 转化后的16进制形式字符串"""return hex(a)[2:].zfill(k)def bin2hex(a, k):"""比特串转化为16进制的字符串,前补0补齐k位数:param a: 待转化的比特串:param k: 补齐后的字符串长度:return: 长度为k的16进制字符串"""#return hex(int(a, 2))[2:].zfill(k)#对于python2需去除长整型引入的字符Lreturn hex(int(a, 2))[2:].replace('L', '').zfill(k)def msg_fill(msg_bin):"""对消息进行填充。填充后的消息满足:(l+1+k) mod 512 = 448 k取最小值:param msg_bin: 比特串形式的消息:return: 填充后的消息(比特串形式)"""l = len(msg_bin)k = 448 - (l + 1) % 512if k < 0:k += 512l_bin = int2bin(l, 64)msg_filled = msg_bin + '1' + '0' * k + l_binreturn msg_filleddef iteration_func(msg):"""迭代压缩:param msg: 填充后的比特串消息:return: 迭代压缩后的消息,长度为64的字符串"""# 将填充后的消息按512比特进行分组n = len(msg) // 512b = []for i in range(n):b.append(msg[512 * i:512 * (i + 1)])# 对消息进行迭代压缩v = [int2bin(iv, 256)]for i in range(n):v.append(cf(v[i], b[i]))return bin2hex(v[n], 64)def msg_extension(bi):"""消息扩展, 将消息分组bi扩展生成132个字W0, W1, · · · , W67, W0', W1', · · · , W63',用于压缩函数CF:param bi: 填充后的消息分组,长度为512的比特串:return: w, w1 扩展后的消息,w为68字的list, w1为64字的list。字以整数存储"""# 将消息分组Bi划分为16个字W0, W1, · · · , W15w = []for j in range(16):w.append(int(bi[j * 32:(j + 1) * 32], 2))for j in range(16, 68):w_j = p1(w[j - 16] ^ w[j - 9] ^ rotate_left(w[j - 3], 15)) ^ rotate_left(w[j - 13], 7) ^ w[j - 6]w.append(w_j)w1 = []for j in range(64):w1.append(w[j] ^ w[j + 4])return w, w1def cf(vi, bi):"""压缩函数:param vi: 比特串(256位):param bi: 填充后的消息分组(512位比特串):return: 压缩后的比特串(256位)"""# 对bi进行消息扩展w, w1 = msg_extension(bi)# 将vi拆分为 a~h 8个字t = []for i in range(8):t.append(int(vi[i * 32:(i + 1) * 32], 2))a, b, c, d, e, f, g, h = tfor j in range(64):ss1 = rotate_left((rotate_left(a, 12) + e + rotate_left(t_j(j), j)) % MAX, 7)ss2 = ss1 ^ rotate_left(a, 12)tt1 = (ff(a, b, c, j) + d + ss2 + w1[j]) % MAXtt2 = (gg(e, f, g, j) + h + ss1 + w[j]) % MAXd = cc = rotate_left(b, 9)b = aa = tt1h = gg = rotate_left(f, 19)f = ee = p0(tt2)vi_1 = int2bin(a, 32) + int2bin(b, 32) + int2bin(c, 32) + int2bin(d, 32) \+ int2bin(e, 32) + int2bin(f, 32) + int2bin(g, 32) + int2bin(h, 32)vi_1 = int(vi_1, 2) ^ int(vi, 2)return int2bin(vi_1, 256)def rotate_left(a, k):"""(字)循环左移k比特运算:param a: 待按位左移的比特串:param k: 左移位数:return:"""k = k % 32return ((a << k) & 0xFFFFFFFF) | ((a & 0xFFFFFFFF) >> (32 - k))def p0(x):"""置换函数P0:param x: 待置换的消息(字):return: 置换后的消息(字)"""return x ^ rotate_left(x, 9) ^ rotate_left(x, 17)def p1(x):"""置换函数P1:param x: 待置换的消息(字):return: 置换后的消息(字)"""return x ^ rotate_left(x, 15) ^ rotate_left(x, 23)def t_j(j):"""常量"""if j <= 15:return 0x79cc4519else:return 0x7a879d8adef ff(x, y, z, j):"""布尔函数ff"""if j <= 15:return x ^ y ^ zelse:return (x & y) | (x & z) | (y & z)def gg(x, y, z, j):"""布尔函数gg"""if j <= 15:return x ^ y ^ zelse:return (x & y) | ((x ^ 0xFFFFFFFF) & z)def sm3(msg):"""sm3加密主函数:param msg: 待加密的字符串:return: sm3加密后的字符串"""# 字符串转化为比特串s_bin = str2bin(msg)# 对消息进行填充s_fill = msg_fill(s_bin)# 对填充后的消息进行迭代压缩s_sm3 = iteration_func(s_fill)# 对于python2需要删除因长整型而引入的末尾的L字符,python3不存在该问题return s_sm3.upper().replace("L", "")if __name__ == "__main__":s1 = 'abc's1_sm3 = sm3(s1)print("{} ==> {}".format(s1, s1_sm3))s2 = 'hello's2_sm3 = sm3(s2)print("{} ==> {}".format(s2, s2_sm3))

代码执行结果:

abc ==> 66C7F0F462EEEDD9D1F2D46BDC10E4E24167C4875CF2F7A2297DA02B8F4BA8E0
hello ==> BECBBFAAE6548B8BF0CFCAD5A27183CD1BE6093B1CCECCC303D9C61D0A645268

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

注:20220820修改bin2hex函数,去除python2的长整型引入的字符“L”

python实现sm3加密算法相关推荐

  1. java采用sm文件加密sm_Java sm3加密算法的实现

    1.准备工作 所需jar包: bcprov-jdk15on-1.59.jar commons-lang3-3.1.jar 对应的maven依赖 org.bouncycastle bcprov-jdk1 ...

  2. Python实现SPN加密算法

    Python实现SPN加密算法 参考: 密码学入门(一):用Python实现对称加密算法 <密码学原理与实践> #S盒 S_Box = [0xE, 0x4, 0xD, 0x1, 0x2, ...

  3. python实现RC4加密算法

    python实现RC4加密算法 RC4加密算法是一种对称的加密算法,加密解密用一个函数即可完成.在网上有好多实现算法写的非常复杂,加密解密用了两个不同的方法.因此在这里分享一个Python实现的RC4 ...

  4. python实现非对称加密算法_Python3非对称加密算法RSA实例详解

    本文实例讲述了Python3非对称加密算法RSA.分享给大家供大家参考,具体如下: python3 可以使用 Crypto.PublicKey.RSA 和 rsa 生成公钥.私钥. 其中 python ...

  5. python实现sha1加密算法

    本文主要记录一下 python实现sha1的封装过程. 目录 一.程序源码 二.调用测试 一.程序源码 """ 使用sha1加密算法,返回str加密后的字符串 " ...

  6. 使用Python实现RSA加密算法及详解RSA算法

    代码已经放上github : https://github.com/chroje/RSA 一.非对称加密算法 1.乙方生成两把密钥(公钥和私钥).公钥是公开的,任何人都可以获得,私钥则是保密的. 2. ...

  7. python实现非对称加密算法_Python使用rsa模块实现非对称加密与解密

    Python使用rsa模块实现非对称加密与解密 1.简单介绍: RSA加密算法是一种非对称加密算法 是由已知加密密钥推导出解密密钥在计算上是不可行的"密码体制.加密密钥(即公开密钥)PK是公 ...

  8. Python实现RSA加密算法

    RSA介绍 RSA加密算法是由美国麻省理工学院的3名密码学者Rivest.Shamir.Adleman提出的一种基于大合数因式分解困难性的公共弄开密钥密码.由于它的安全.易懂,因此已成为目前应用最广的 ...

  9. Python实现AES加密算法(无第三方库)

    概述 AES加密算法,即Rijndael算法,是一种对称分组密码,它可以使用长度为128.192和256位的密钥处理128位的数据块.本文将用Python实现密钥长度为128位的AES算法,若想要详细 ...

  10. rc4加密算法c语言实现,python实现RC4加密算法

    1. 背景介绍 1.1 RC4算法 在密码学中,RC4(来自Rivest Cipher 4的缩写)是一种流加密算法,密钥长度可变.它加解密使用相同的密钥,因此也属于对称加密算法.RC4是有线等效加密( ...

最新文章

  1. Matlab与线性代数 -- 零矩阵
  2. 转录组分析_高级转录组分析和R数据可视化
  3. python数据结构推荐书-自己想学数据结构,有大佬能推荐一下看什么书吗?
  4. SpringMVC跳转页面默认类型和转发、重定向的使用
  5. springMVC 前台向后台传数组
  6. python识别图片指定位置文字_python批量识别图片指定区域文字内容
  7. 6 redis 编译失败_Centos7.8环境搭建Redis主从复制和哨兵模式
  8. 【小技巧】【堆】【优先队列】优先队列初始化
  9. 是否需要配置环境变量,比如maven,jdk等
  10. 利用hacking搜索技巧搜索到你任何特定想要的内容
  11. el-form 动态校验规则_动态多线程敏感信息泄露检测工具
  12. [转载]百分之百自动登录2345王牌技术员联盟源代码(delphi)
  13. 【ArcGIS|空间分析】地形特征相关计算
  14. c++ 中 try catch throw异常
  15. 局域网服务器共享文件夹设置,局域网服务器共享文件访问权限管理方法
  16. 如果让你来制作一个访问量很高的大型网站,你会如何来管理所有CSS文件、JS与图片?
  17. 常见的几种ADSL 路由器的端口映射方法
  18. 软件作业2:时事点评-红芯浏览器事件
  19. 【Axure交互教程】 可滑动的标签页效果
  20. java函数加不加static有何不同

热门文章

  1. 电脑出现问题,你的PIN不可用。请单击以重新设置。
  2. 禁用“微软 Windows 10 易升”
  3. c语言棋盘上的麦粒switch,C语言教材后习题及答案.doc
  4. 计算机安装微信打不开,电脑版微信打不开解决方法
  5. 【项目一、xxx病虫害检测项目】2、网络结构尝试改进:Resnet50、SE、CBAM、Feature Fusion
  6. 宝塔面板6.9.0一键破解脚本
  7. vue+element pagination分页的二次封装,带首页末页功能
  8. 缺少比较器,运放来救场!(运放当做比较器电路记录)
  9. 手机App性能测试工具Genymotion安卓模拟器使用和简介
  10. 利用电影直播赚钱的方法(几乎零成本、很多人不知道)