国产环境为什么要推广国密算法
- 自主可控,不必依赖于国外的技术,更符合国情
- 安全性更高,目前来说国密算法不会被破解,重要信息不会存在泄露危险
- 性能更好
暂且不管下面的阐述是否是睁着眼睛说的,至多第一点是不可否认的
定义
国产明码算法(国密算法)是指国家明码局认定的国产商用明码算法,实现商用明码算法的加密、解密和认证等性能
国产商业环境目前次要应用公开的SM2(非对称算法)
、SM3(哈希算法)
、SM4(对称算法)
罕用国密算法
SM1
- 分组加密算法,分组长度,密钥长度都是
128bit
- 对称加密算法
- 算法平安窃密水平和
AES
相当 - 算法不公开,以
IP
核模式存在于芯片中,须要通过加密芯片接口调用,采纳硬件实现
SM2
- 非对称加密算法,基于椭圆曲线明码的公钥明码算法规范,其秘钥长度
256bit
,蕴含数字签名、密钥替换和公钥加密 - 用于替换
RSA/DH/ECDSA/ECDH
等国内算法 SM2
采纳的是ECC 256
位的一种,其平安强度比RSA 2048
位高,且运算速度快于RSA
SM3
- 明码杂凑算法,报文摘要算法,不可逆
- 在
SHA-256
根底上改良实现的一种算法,采纳Merkle-Damgard
构造,音讯分组长度为512bit
,输入的摘要值长度为256bit
- 用于代替
MD5/SHA-1/SHA-2
等国内算法 - 实用于数字签名和验证、音讯认证码的生成与验证以及随机数的生成
SM4
- 分组对称明码算法
AES
算法具备雷同的密钥长度、分组长度,都是128bit
- 用于代替
DES/AES
等国内算法 -
算法蕴含几种常见加密解密模式
-
ECB
模式次要逻辑
- 把数据依照肯定长度字节分段进行加密或者解密,最初一段有余固定长度的话补 0 或者补
F
- 最初把计算出来的数据连在一起就失去明文或者密文
长处
- 简略
- 有利于并行计算
- 误差不会被传递
毛病
- 不能暗藏明文的模式
- 可能对明文进行主动攻击
- 把数据依照肯定长度字节分段进行加密或者解密,最初一段有余固定长度的话补 0 或者补
-
CBC
模式是一种循环模式
次要逻辑
- 把数据依照固定长度分组,最初一组数据长度有余的话填充指定数据
- 第一组数据与初始化向量
iv
进行异或运算,产生的后果执行加密失去第一组密文 - 第二组数据与第一组加密后果进行异或后的后果,执行加密失去第二组密文
- 最初把所有分组密文拼接在一起失去加密后果
长处
- 不容易主动攻击
- 安全性好于
ECB
,是SSL、IPSec
的规范
毛病
- 不利于并行计算
- 误差传递
- 须要初始化向量
IV
-
SM9
- 用椭圆曲线对实现的基于标识的数字签名算法、密钥替换协定、密钥封装机制和公钥加密与解密算法,包含数字签名生成算法和验证算法,并给出了数字签名与验证算法及其相应的流程
python
国密算法举荐与利用
开源我的项目
https://github.com/duanhongyi/gmssl
SM2 与 SM3 算法
因为 sm2
加密须要生成一个 sm2
对应的椭圆曲线对应的公钥和私钥,然而 gmssl
库没有封装一个随机生成公钥私钥的函数,所以须要拜访一个第三方的网址去获取生成的公钥私钥,网址如下
https://const.net.cn/tool/sm2/genkey/
把生成的公钥和私钥输出作为参数,填入如下代码
初始化定义,非对称加密须要提供公钥和私钥参数
from gmssl import sm2, func
private_key = '00B9AB0B828FF68872F21A837FC303668428DEA11DCD1B24429D0C99E24EED83D5'
public_key = 'B9C9A6E04E9C91F7BA880429273747D7EF5DDEB0BB2FF6317EB00BEF331A83081A6994B8993F3F5D6EADDDB81872266C87C018FB4162F5AF347B483E24620207'
sm2_crypt = sm2.CryptSM2(public_key=public_key, private_key=private_key, asn1=True)
加密和解密
data = b"test"
for _ in range(5):
enc_data = sm2_crypt.encrypt(data)
print(f'encrypted data len {len(enc_data.hex())}: {enc_data.hex()}')
dec_data = sm2_crypt.decrypt(enc_data)
print(f'decrypted data len {len(dec_data)}: {dec_data}\n')
assert dec_data == data
生成的打印输出如下,生成密文的长度都是固定的 200,发现每次生成的密文都是不同的,在加密过程中退出了salt
,防止了雷同明文映射到雷同密文造成的不安全性
encrypted data len 200: 42a29aa33143985e14ae37ccdba89704595008e561af51cb7d88d2c9663468492b0d08a431fa5cd5b92e785ffd9cb858a69d71da82ddb3ddfeaa6e5e765e25cfb68bd4b307c63bc7fe844045159e8cbdbecbe4e3c31359c5f87669abb1dc6e431ad82632
decrypted data len 4: b'test'
encrypted data len 200: a797d8e1a205e1e50d60895b29d056eecd6d8e0f58ececf283680d695a007c24c2f182ce9601a500e3b755f6f530d3490b4efc43c242b9bdfff64253099792e8a7c4fa9692a59961fc7b6ef35a738a27d1c262f7e4a39190c64e1b8c2ff7c9ffa48748a6
decrypted data len 4: b'test'
encrypted data len 200: cd010a36cb272c9fc1f355e9e707554c972ba0ec27fe171a137b7d9165a7fe7f9913633333b1290909ce28f73973aa84fe666a97335c6d12f17fd724c87cc2bd37bc4581118fe049cd08ef963ffce0d84cd779f7c6b875c17a88b864115bca71a43cfbd9
decrypted data len 4: b'test'
encrypted data len 200: 88f5c05e7830c8b70320f2c40673d9aa0fd961535214825765d81e85e9c47e6bdb064086c1b462b2a735aa82ea5ed9668f8611a16c811247ff9dad92f9d572f983d5d2dcc26ae808fdfa4fb7044245bf9066ea11a28fb18208091e060da7c62ea6145266
decrypted data len 4: b'test'
encrypted data len 200: a5ef6804476fe7442c181aa70df95eae31c4ff59fb70002f7dfca1e8d50f987c8917ce0c9754c19ec5696bfcd71ff686847ca5c62f8c49654388ff1b463393aed40d3a53876587c53aa33aee466248d0fceb4f6c97ada7b25194d0990275b97c81fa32d1
decrypted data len 4: b'test'
签名和验证
data = b"test"
for _ in range(5):
random_hex_str = func.random_hex(sm2_crypt.para_len)
print(f'random hex str len:{len(random_hex_str)}: {random_hex_str}')
sign = sm2_crypt.sign(data, random_hex_str)
print(f'sign len: {len(sign)}: {sign}\n')
assert sm2_crypt.verify(sign, data)
输入后果
每次签名的时候都会应用一个随机 16 进制字符串,同时输入的签名长度也不固定
random hex str len:64: ae41ca267f156a5e8bc2b5842138518df2187c4b81185502eaba534cecd473de
sign len: 144: 3046022100b32014d803f37c731d2612e6b79d8af8ab0e9a70bca60bb426e69d816c9a5c6e02210092d08bf619a8b465c40333b0151c38f8ed83e9243778eb16aab158dbbdea146c
random hex str len:64: 5becbd479334bf24177d1cd945d44a6b6a645ab7ff3c7cc13a1ced27400c22dd
sign len: 140: 304402203bca856f3714692050e0450b60199ee84933727c18c86afb966b92a67e10acb802201e13845e809f2f91d893602422fcf227826465f3ff388ec619ecfae09272f49e
random hex str len:64: 80e8a41ec38ed14c48d20fd6d3dba36e8e44f699def324032b920aa0024d79b7
sign len: 142: 304502210094a9cafd30d458467eaf63d560f4a76d20961d73171ab48f7a680c29aa6ec093022075bac7f549ca5cf9aef442d202ea1246ce3513a3c90cc0b5478f8d67879b5a1d
random hex str len:64: 7c7dbbca98378d1669c8884e7a9edab4c33227099487cb534c8f42214d4bcde2
sign len: 142: 3045022100c195ebbf1610c0e73739f702e4f486f40fa71578f8afcdf171fae3019421520702202978040d809d09e8c39dc459e3386b06877276c6129e355a70b16e2cd2d883b6
random hex str len:64: ac3e6789f816a4058eb0e70611ea784570cbba2aa885f7a847e9801ae2445f89
sign len: 142: 3045022100cb2a28cb29e1e6435d38d893e448a0c8aad1cc0bc4c532f09889f4dd70c3f8b5022001652e812c8f4828ddd6f4ce02b221f687f8f8cbe58263043a9e8f17f36793f3
sm3
算法是一种 hash
算法
from gmssl import sm3, func
for _ in range(3):
value = sm3.sm3_hash(func.bytes_to_list(b"abc"))
print(f'len: {len(value)}: {value}')
运行后果是三个雷同的 64 位 hash
值
len: 64: 66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0
len: 64: 66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0
len: 64: 66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0
如果有相似于签名和校验的须要,还是举荐配合 sm2
进行
data = b"test"
for _ in range(5):
sign = sm2_crypt.sign_with_sm3(data)
print(f'len: {len(sign)} {sign}\n')
assert sm2_crypt.verify_with_sm3(sign, data)
输入后果如下,每次生成的签名长度不固定,值也不同
len: 144 3046022100e1c3aa1b1de8be08a6c727e58d577fb7632adc08b49455b88aaef405cc80ae6c022100abbf44d84c5eeed6764b9aaeda044dc80f3e997f9c8d04dd75f7a73c6d21a353
len: 142 30450220026c1c8b3e56eacab664d34e33d90e95235fc16eec701df4de2eca699ba7d1cb022100e3c4158fd387e93c9a79a5e2d3d4d92a0aabcd8f72a0bc79fcd3e20a549599b9
len: 142 3045022100e0d049d45893be28cea5221fbe560fa2d519e191ea46aa8fa0dbaf181ae10afe02201ef02258c2f867de34c2ecc16184bada7e35fb515e1fed2e7bbfa11f52a3a8d0
len: 142 30450221009d68b397f288e246e647aa288bb0e8fa038011d6381dd30130849c0756a1defb02200c0d172deab8765159f78e0de8a9d5d3bfc0df9e366902da470f05a4c253f377
len: 140 3044022061c7bef3bcb7a2fd85ea1d8995e0bf05e9ec9b5ba5ef882728d73402876258ac02202d73fe00c8a552d45d8934104c5857d8e23b046e1f98ded8ebef26f8bcf30d92
SM4
算法
初始化定义如下,因为是分组加密算法,须要应用一个密钥,密钥长度为128bit
上面定义 key
的组成,全是 ascii
字符,每个字符一个字节,所以须要 16 位字符,超过的字符会被疏忽
测试加密明文数据是test-value
from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT
key = b'1234567812345678'
value = b'test-value'
crypt_sm4 = CryptSM4()
测试 ecb
模式加密解密
for _ in range(5):
crypt_sm4.set_key(key, SM4_ENCRYPT)
encrypt_value = crypt_sm4.crypt_ecb(value)
print(f'original len: {len(value)} {value}, encrypt len: {len(encrypt_value)} {encrypt_value}')
crypt_sm4.set_key(key, SM4_DECRYPT)
decrypt_value = crypt_sm4.crypt_ecb(encrypt_value)
assert value == decrypt_value
输入后果如下,能够获取到后果如下
每次加密计算的密文后果是一样的,所以如果密钥泄露的话,数据就不平安了
生成的密文长度取决于明文长度,密文长度为16 * (明文长度 //16 + 1)
original len: 10 b'test-value', encrypt len: 16 b'\xaaa\xe5"YiT\x1d\x84\xa3e2\xec9\x80\xd8'original len: 10 b'test-value', encrypt len: 16 b'\xaaa\xe5"YiT\x1d\x84\xa3e2\xec9\x80\xd8'
original len: 10 b'test-value', encrypt len: 16 b'\xaaa\xe5"YiT\x1d\x84\xa3e2\xec9\x80\xd8'original len: 10 b'test-value', encrypt len: 16 b'\xaaa\xe5"YiT\x1d\x84\xa3e2\xec9\x80\xd8'
original len: 10 b'test-value', encrypt len: 16 b'\xaaa\xe5"YiT\x1d\x84\xa3e2\xec9\x80\xd8'
测试 cbc
模式加密解密,须要定义一个初始化向量
iv = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
for _ in range(5):
crypt_sm4.set_key(key, SM4_ENCRYPT)
encrypt_value = crypt_sm4.crypt_cbc(iv, value)
print(f'encrypt len: {len(encrypt_value)} {encrypt_value}')
crypt_sm4.set_key(key, SM4_DECRYPT)
decrypt_value = crypt_sm4.crypt_cbc(iv, encrypt_value)
assert value == decrypt_value
失去后果如下,每次加密后果都一样
encrypt len: 16 b'\xaaa\xe5"YiT\x1d\x84\xa3e2\xec9\x80\xd8'encrypt len: 16 b'\xaaa\xe5"YiT\x1d\x84\xa3e2\xec9\x80\xd8'
encrypt len: 16 b'\xaaa\xe5"YiT\x1d\x84\xa3e2\xec9\x80\xd8'encrypt len: 16 b'\xaaa\xe5"YiT\x1d\x84\xa3e2\xec9\x80\xd8'
encrypt len: 16 b'\xaaa\xe5"YiT\x1d\x84\xa3e2\xec9\x80\xd8'
golang
国密算法实现举荐
https://github.com/tjfoc/gmsm
参考浏览
国密算法介绍 - 知乎
GMSSL
我的项目readme