SM4加密算法例程(新增CTR模式)
2024-01-08 16:39:00
说明
SM4和AES只是加密算法不同,使用起来几乎没有区别,AES相关的例程可以参考:
本文主要介绍SM4加密算法,并提供库里没有的CTR模式模式
加密模式介绍
ECB模式(Electronic Codebook):
特点:
- 独立性: 每个明文块都独立地使用相同的密钥进行加密,因此加密过程是相互独立的。
- 并行性: 由于每个块之间没有依赖关系,ECB模式具有较好的并行性,可以同时加密多个块。
加密过程:
-
将明文划分为固定大小的块(例如128位)。
-
对每个块独立使用AES加密算法,使用相同的密钥。
-
输出得到相应的密文块。
CBC模式(Cipher Block Chaining):
特点:
- 链接性: 每个明文块在加密之前都与前一个密文块进行异或运算,建立起块之间的链接,增加了安全性。
- 初始块: 使用初始化向量(IV)引导第一个块的加密,避免了相同的明文块生成相同的密文块。
加密过程:
-
使用初始化向量(IV)与第一个明文块进行异或运算。
-
对异或的结果使用AES加密算法,得到第一个密文块。
-
将第一个密文块作为下一个明文块的IV,继续进行异或和加密。
-
重复这个过程直到加密完所有的块。
CTR模式(Counter):
特点:
- 并行性: 由于每个块都被视为一个计数器的值,不需要保持块之间的状态,因此CTR模式具有良好的并行性。
- 计数器: 每个块都使用一个唯一的计数器值,避免了相同的明文块生成相同的密文块。
加密过程:
- 生成一个初始计数器值(Counter)和初始化向量(IV)。
- 将计数器值与IV组合作为输入,使用AES加密算法生成伪随机流。
- 将伪随机流与明文块进行异或运算,得到密文块。
- 更新计数器值,继续生成伪随机流,重复以上步骤直到加密完所有的块。
AES和SM4的区别
设计和标准制定
- AES: 由美国国家标准技术研究所(NIST)于2001年制定,是国际上广泛认可的加密标准。
- SM4: 由中国国家密码管理局在2006年制定,主要在中国国内使用。
密钥长度
- AES: 支持128位、192位和256位的密钥长度,分别称为AES-128、AES-192和AES-256。
- SM4: 使用固定的128位密钥。
分组长度
- AES: 使用128位的分组长度。
- SM4: 同样使用128位的分组长度。
轮数
- AES: 轮数取决于密钥长度,分别为10轮(AES-128)、12轮(AES-192)和14轮(AES-256)。
- SM4: 固定为32轮。
S盒(Substitution Box)
- AES: 使用固定的S盒,是一个预定义的字节替换表。
- SM4: 使用非线性的S盒,通过运算生成。
应用领域
- AES: 作为国际上广泛应用的加密算法,适用于各种领域的安全通信和数据保护。
- SM4: 主要在中国国内使用,用于信息安全领域。
国际认可
- AES: 经过全球范围内的广泛评估,得到广泛认可。
- SM4: 目前主要在中国国内应用,国际认可度相对较低。
通过对比这两种算法的设计、应用和性能特征,可以更好地理解它们在不同背景下的使用场景和优势。在选择使用哪种算法时,应考虑特定的安全需求和国际标准。
代码
输出
ECB ENCYRPT(hex): 9a991f25e3303e12173f04f698ed5f4d
ECB DECYRPT(str): 1234567890abcdef
CBC ENCYRPT(hex): d2d68ed9fe06cb40c9a150aa5917f15fa80538810c8117273f53ac7a0735b8f5
CBC DECYRPT(str): 1234567890abcdef123456789abcdef0
CRT ENCYRPT(hex): abab2c11d606092a2e0f6594fb893a2b7aa45f0c5b207da83e4bb3eb754c1f00
CRT DECYRPT(str): 1234567890abcdef123456789abcdef0
源代码
from pysm4 import encrypt_ecb, decrypt_ecb, encrypt_cbc, decrypt_cbc
import base64
sm4_key = "1234567890123456";
sm4_iv = "1234567890abcdef";
sm4_in = "1234567890abcdef123456789abcdef0";
def SM4_CTR(data, key, iv, byteorder = "little"):
'''入参和返回值均为bytes类型'''
i = 0
ret = []
groups_num = len(data) // 16
# bytes 转 int
if byteorder == "little":
iv_int = int.from_bytes(iv[0:4], byteorder)
else:
iv_int = int.from_bytes(iv[12:16], byteorder)
for i in range(groups_num):
temp_bs64 = encrypt_ecb(iv, key)
temp_bytes = base64.b64decode(temp_bs64)
for j in range(16):
ret.append(data[i*16+j] ^ temp_bytes[j])
iv_int += 1
if byteorder == "little":
iv = iv_int.to_bytes(4, byteorder) + iv[4:]
else:
iv = iv[:12] + iv_int.to_bytes(4, byteorder)
if (len(data) % 16):
temp_bs64 = encrypt_ecb(iv, key)
temp_bytes = base64.b64decode(temp_bs64)
for j in range(len(data) % 16):
ret.append(data[i*16+j] ^ temp_bytes[j])
return ret
def ecb_test():
ret = encrypt_ecb(sm4_in.encode(), sm4_key.encode())
print("ECB ENCYRPT(hex): ", base64.b64decode(ret).hex()[:32])
ret = decrypt_ecb(ret, sm4_key.encode())
print("ECB DECYRPT(str): ", ret[:16])
def ccb_test():
ret = encrypt_cbc(sm4_in.encode(), sm4_key.encode(), sm4_iv.encode())
print("CBC ENCYRPT(hex): ", base64.b64decode(ret).hex()[:64])
ret = decrypt_cbc(ret, sm4_key.encode(), sm4_iv.encode())
print("CBC DECYRPT(str): ", ret[:32])
def ctr_test():
ret = SM4_CTR(sm4_in.encode(), sm4_key.encode(), sm4_iv.encode(), "big")
print("CRT ENCYRPT(hex): ", bytes(ret).hex())
ret = SM4_CTR(bytes(ret), sm4_key.encode(), sm4_iv.encode(), "big")
print("CRT DECYRPT(str): ", bytes(ret).decode())
if __name__ == '__main__':
ecb_test()
ccb_test()
ctr_test()
文章来源:https://blog.csdn.net/qq_36973838/article/details/135390412
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!