2010 年开始,我国国家密码管理局就已经开始陆续发布了一系列国产加密算法,这其中就包括 SM1、SM2、SM3 、SM4、SM7、SM9、ZUC(祖冲之加密算法)等,SM 代表商密,即商业密码,是指用于商业的、不涉及国家秘密的密码技术。SM1 和 SM7 的算法不公开,其余算法都已成为 ISO/IEC 国际标准。目前应用较多的是SM2、SM3和SM4算法,这三者用法不一。
加密算法 | 定义 | 应用领域 | 特点 | 类似算法 | 是否公开 |
---|---|---|---|---|---|
sm1 | 对称加密算法 | 芯片 | 分组长度、密钥长度均为128比特 | DES、3DES | 不公开 |
sm2 | 非对称加密算法 | 数据加密 | ECC椭圆曲线密码机制256位,相比RSA处理速度快,消耗更少 | RSA、RSA4096 | 公开 |
sm3 | 散列函数算法 | 完整性校验 | 哈希算法安全性及效率与SHA-256相当,压缩函数更复杂 | SHA1、SHA-256、SHA-384、SHA-512 | 公开 |
sm4 | 对称加密算法 | 数据加密和局域网产品 | 分组长度、密钥长度均为128比特,计算轮数多 | DES、AES | 公开 |
sm7 | 对称加密算法 | 非接触式IC卡 | 分组长度、密钥长度均为128比特 | 不公开 | |
sm9 | 标识加密算法(IBC) | 端对端离线安全通讯 | 加密强度等同于3072位密钥的RSA加密算法 | 公开 | |
ZUC | 对称加密算法 | 移动通信、4G网络 | 流密码 | 公开 |
SM2算法和RSA算法都是公钥密码算法,SM2算法是一种更先进安全的算法,在我们国家商用密码体系中被用来替换RSA算法。
随着密码技术和计算机技术的发展,目前常用的1024位RSA算法面临严重的安全威胁,我们国家密码管理部门经过研究,决定采用SM2椭圆曲线算法替换RSA算法。
密文数据顺序简介
SM2非对称加密的结果由C1,C2,C3三部分组成。其中C1是根据生成的随机数计算出的椭圆曲线点,C2是密文数据,C3是SM3的摘要值。最开始的国密标准的结果是按C1,C2,C3顺序存放的,新标准的是按C1,C3,C2顺序存放的,因此我们这边在做SM2加密时新增了密文数据顺序设置,用以兼容之前的SM2算法加密。
import base64
import binascii
from gmssl import sm2, func
def test_sm2():
private_key = '00B9AB0B828FF68872F21A837FC303668428DEA11DCD1B24429D0C99E24EED83D5'
public_key = 'B9C9A6E04E9C91F7BA880429273747D7EF5DDEB0BB2FF6317EB00BEF331A83081A6994B8993F3F5D6EADDDB81872266C87C018FB4162F5AF347B483E24620207'
sm2_crypt = sm2.CryptSM2(
public_key=public_key, private_key=private_key)
data = b"111"
enc_data = sm2_crypt.encrypt(data)
#print("enc_data:%s" % enc_data)
#print("enc_data_base64:%s" % base64.b64encode(bytes.fromhex(enc_data)))
dec_data = sm2_crypt.decrypt(enc_data)
print(b"dec_data:%s" % dec_data)
assert data == dec_data
print("-----------------test sign and verify---------------")
random_hex_str = func.random_hex(sm2_crypt.para_len)
sign = sm2_crypt.sign(data, random_hex_str)
print('sign:%s' % sign)
verify = sm2_crypt.verify(sign, data)
print('verify:%s' % verify)
assert verify
def test_sm2sm3():
private_key = "3945208F7B2144B13F36E38AC6D39F95889393692860B51A42FB81EF4DF7C5B8"
public_key = "09F9DF311E5421A150DD7D161E4BC5C672179FAD1833FC076BB08FF356F35020"\
"CCEA490CE26775A52DC6EA718CC1AA600AED05FBF35E084A6632F6072DA9AD13"
random_hex_str = "59276E27D506861A16680F3AD9C02DCCEF3CC1FA3CDBE4CE6D54B80DEAC1BC21"
sm2_crypt = sm2.CryptSM2(public_key=public_key, private_key=private_key)
data = b"message digest"
print("-----------------test SM2withSM3 sign and verify---------------")
sign = sm2_crypt.sign_with_sm3(data, random_hex_str)
print('sign: %s' % sign)
verify = sm2_crypt.verify_with_sm3(sign, data)
print('verify: %s' % verify)
assert verify
if __name__ == '__main__':
test_sm2()
test_sm2sm3()
SM3国密杂凑在线工具。支持常规的字符SM3计算,亦支持文件SM3计算。文件无需上传至服务器,且不存在任何限制,在浏览器内即可完成SM3哈希值计算。编码类型(utf8/gbk等)只影响常规字符SM3计算。SM3国密相关技术细节请参考:《SM3密码杂凑算法》
from gmssl import sm3, func
if __name__ == '__main__':
y = sm3.sm3_hash(func.bytes_to_list(b"abc"))
print(y)
SM4.0(原名SMS4.0)是中华人民共和国政府采用的一种分组密码标准,由国家密码管理局于2012年3月21日发布。相关标准为“GM/T 0002-2012《SM4分组密码算法》(原SMS4分组密码算法)”。
在商用密码体系中,SM4主要用于数据加密,其算法公开,分组长度与密钥长度均为128bit,加密算法与密钥扩展算法都采用32轮非线性迭代结构,S盒为固定的8比特输入8比特输出。
SM4.0中的指令长度被提升到大于64K(即64×1024)的水平,这是SM 3.0规格(渲染指令长度允许大于512)的128倍。
from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT
key = b'3l5butlj26hvv313'
value = b'111'
iv = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
crypt_sm4 = CryptSM4()
crypt_sm4.set_key(key, SM4_ENCRYPT)
encrypt_value = crypt_sm4.crypt_ecb(value)
crypt_sm4.set_key(key, SM4_DECRYPT)
decrypt_value = crypt_sm4.crypt_ecb(encrypt_value)
assert value == decrypt_value
crypt_sm4.set_key(key, SM4_ENCRYPT)
encrypt_value = crypt_sm4.crypt_cbc(iv , value)
crypt_sm4.set_key(key, SM4_DECRYPT)
decrypt_value = crypt_sm4.crypt_cbc(iv , encrypt_value)
assert value == decrypt_value
from gmssl import sm9
if __name__ == '__main__':
idA = 'a'
idB = 'b'
print ("-----------------test sign and verify---------------")
master_public, master_secret = sm9.setup ('sign')
Da = sm9.private_key_extract ('sign', master_public, master_secret, idA)
message = 'abc'
signature = sm9.sign (master_public, Da, message)
assert (sm9.verify (master_public, idA, message, signature))
print ("\t\t\t success")
print ("-----------------test key agreement---------------")
master_public, master_secret = sm9.setup ('keyagreement')
Da = sm9.private_key_extract ('keyagreement', master_public, master_secret, idA)
Db = sm9.private_key_extract ('keyagreement', master_public, master_secret, idB)
xa, Ra = sm9.generate_ephemeral (master_public, idB)
xb, Rb = sm9.generate_ephemeral (master_public, idA)
ska = sm9.generate_session_key (idA, idB, Ra, Rb, Da, xa, master_public, 'A', 128)
skb = sm9.generate_session_key (idA, idB, Ra, Rb, Db, xb, master_public, 'B', 128)
assert (ska == skb)
print ("\t\t\t success")
print ("-----------------test encrypt and decrypt---------------")
master_public, master_secret = sm9.setup ('encrypt')
Da = sm9.private_key_extract ('encrypt', master_public, master_secret, idA)
message = 'abc'
ct = sm9.kem_dem_enc (master_public, idA, message, 32)
pt = sm9.kem_dem_dec (master_public, idA, Da, ct, 32)
assert (message == pt)
print ("\t\t\t success")
https://github.com/gongxian-ding/gmssl-python
https://github.com/duanhongyi/gmssl
https://www.lzltool.com/SM2