python实现sm3加密算法
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加密算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows下用cmd命令安装及卸载服
- 下一篇: 4款超实用绘图软件