近期做项目时需要使用SM4的OFB模式,但是开源工具箱gmssl中只有sm4的ecb和cbc模式,openssl中也没有提供SM4的python接口
于是基于gmssl的sm4模块写了一个ofb模式,多线程,没有进行下一步封装。
写在前面:gmssl还是很值得学习密码学的同学们去读一读的
加密:
from gmssl.func import xor, list_to_bytes, bytes_to_list, padding
from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT
import threading
# OFB加密模式
# M为一个NAL中的RBSP,加密主密钥key必须是128bit
stream_key = [] # 列表的列表,里面存放每次流密码加密时的密钥
output_data = [] # 存放密文
def XOR(M, i):
global output_data
m = i * 16
n = (i + 1) * 16
output_data += xor(M[m:n], stream_key[i + 1])
# M是bytes类型
def ofb_Encrypt(key, iv, M):
global stream_key
global output_data
# 初始化
crypt_sm4 = CryptSM4()
# 设置加密密钥
crypt_sm4.set_key(key, SM4_ENCRYPT)
M = bytes_to_list(M)
M_value = padding(M) # padding函数可以补齐
#print('待加密补位后的明文的十进制列表', M_value)
# 产生密钥流 流多少次把M加密完
stream_num = int(len(M_value) / 16)
# 初始向量补齐 取前16字节
iv = padding(bytes_to_list(iv))
iv = iv[0:16]
stream_key.append(iv)
for i in range(stream_num):
temp = crypt_sm4.one_round(crypt_sm4.sk, stream_key[i])
stream_key.append(temp)
t = threading.Thread(target=XOR, args=[M_value, i, ])
t.start()
t.join()
return list_to_bytes(output_data)
def main():
key = eval(input("加密主密钥16字节:"))
iv = eval(input("流密钥初始向量:"))
M = eval(input("待加密数据:"))
C = ofb_Encrypt(key, iv, M)
print(C)
if __name__ == '__main__':
main()
解密:
from gmssl.func import xor, list_to_bytes, bytes_to_list, unpadding, padding
from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT
import threading
# 存放流密码解密时的密钥
stream_key = []
output_data = []
def XOR(C, i):
global output_data
m = i * 16
n = (i + 1) * 16
output_data += xor(C[m:n], stream_key[i + 1])
def ofb_Decrypt(key, iv, C):
global stream_key
global output_data
crypt_sm4 = CryptSM4()
crypt_sm4.set_key(key, SM4_ENCRYPT)
C_value = bytes_to_list(C)
stream_num = int(len(C_value) / 16)
iv = padding(bytes_to_list(iv))
iv = iv[0:16]
stream_key.append(iv)
for i in range(stream_num):
temp = crypt_sm4.one_round(crypt_sm4.sk, stream_key[i])
stream_key.append(temp)
t = threading.Thread(target=XOR, args=[C_value, i, ])
t.start()
t.join()
output_data = unpadding(output_data)
return list_to_bytes(output_data)
def main():
key = eval(input("解密主密钥16字节:"))
iv = eval(input("流密钥初始向量:"))
C = eval(input("待解密数据:"))
M = ofb_Decrypt(key, iv, C)
print(M)
if __name__