python使用gmssl实现SM4算法的OFB模式

本文介绍了在项目中遇到SM4 OFB模式需求,但开源库gmssl仅支持ECB和CBC模式的情况。为解决此问题,作者基于gmssl实现了SM4的OFB模式,并在多线程环境下进行了应用。虽然未进一步封装,但提供的函数在实际使用中表现出良好效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

近期做项目时需要使用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__ 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值