SM2/SM4怎么使用?

wen python案例 3

SM2/SM4 怎么使用?(附代码与问答)


目录导读

  1. 国密算法背景与必要性
  2. SM2 非对称加密:原理与典型用法
    • SM2 密钥生成
    • SM2 加密/解密流程
    • SM2 签名/验签示例
  3. SM4 对称加密:原理与典型用法
    • SM4 加密模式选择(ECB/CBC/GCM)
    • SM4 加解密代码实战
  4. SM2 + SM4 混合加密体系(推荐方案)
    • 为什么需要混合加密?
    • 混合加密完整流程与代码片段
  5. 常见问题与深度问答(不低于3组)
  6. 总结与最佳实践建议

国密算法背景与必要性

SM2(椭圆曲线公钥密码算法)与 SM4(分组对称密码算法)是我国国家密码管理局发布的商用密码标准,广泛应用于政务、金融、物联网等需要合规密码技术的领域,自2020年起,中国关键信息基础设施必须采用国密算法,因此掌握 SM2/SM4 怎么使用 成为开发者的必备技能。

SM2/SM4怎么使用?

核心区别:

  • SM2(公钥体系):用于数字签名、密钥交换、加密(性能低,适合小数据)。
  • SM4(对称体系):用于大量数据加密(性能高,需安全分发密钥)。

SM2 非对称加密:原理与典型用法

1 SM2 密钥生成

SM2 基于椭圆曲线(推荐曲线参数为 sm2p256v1),使用 Python 的 gmssl 库(或 Java 的 BouncyCastle)生成密钥对:

from gmssl import sm2
# 生成私钥(十六进制字符串)与公钥
private_key = '...'  # 实际应由库生成
public_key = '...'
# 推荐直接使用库函数:
sm2_crypt = sm2.CryptSM2(public_key=public_key, private_key=private_key)

注意: 私钥长度固定为 32 字节,公钥为 64 字节(未压缩形式)。

2 SM2 加密与解密

SM2 加密时自动加入随机数,确保每次密文不同。

data = b"Hello National Secret"
enc_data = sm2_crypt.encrypt(data)
dec_data = sm2_crypt.decrypt(enc_data)
print(dec_data.decode())  # 输出:Hello National Secret

3 SM2 签名与验签

sign = sm2_crypt.sign(data, random_hex='...')  # 随机数应严格安全
assert sm2_crypt.verify(sign, data)  # 验签通过

SM4 对称加密:原理与典型用法

1 加密模式选择

SM4 标准分组大小为 128 位,推荐以下模式:

模式 用途 说明
ECB 不推荐 相同明文输出相同密文,泄露模式
CBC 通用 需要初始向量(IV),并行解密
GCM 推荐 认证加密(AAD),自带完整性校验

2 SM4-CBC 示例(Python)

from gmssl import sm4
key = b'0123456789abcdeffedcba9876543210'  # 16字节密钥
iv = b'0000000000000000'  # 16字节初始向量
crypt_sm4 = sm4.CryptSM4(mode=sm4.SM4_ENCRYPT)
crypt_sm4.set_key(key, iv)
enc_data = crypt_sm4.crypt(b"Secret Data")
crypt_sm4_dec = sm4.CryptSM4(mode=sm4.SM4_DECRYPT)
crypt_sm4_dec.set_key(key, iv)
dec_data = crypt_sm4_dec.crypt(enc_data)

注意: 实际生产务必使用 GCM 模式或 CBC+HMAC 防止篡改。


SM2 + SM4 混合加密体系

1 为什么要混合加密?

  • 性能问题: SM2 加密 100KB 数据耗时约 500ms,不可接受。
  • 密钥分发: SM4 密钥需安全传输,SM2 恰好解决此问题。

方案:

  1. 发送方:生成随机 SM4 会话密钥(16字节),用 SM2 公钥加密该会话密钥。
  2. 发送方:用 SM4 密钥加密实际消息(大数据)。
  3. 接收方:用 SM2 私钥解密得到会话密钥,再用该密钥解密消息。

2 混合加密代码片段

# 发送方
session_key = os.urandom(16)
enc_session_key = sm2_crypt.encrypt(session_key)  # SM2 加密会话密钥
cipher_sm4 = sm4.CryptSM4(mode=sm4.SM4_ENCRYPT)
cipher_sm4.set_key(session_key, iv)
ciphertext = cipher_sm4.crypt(plaintext)  # SM4 加密大数据
# 传输 enc_session_key + ciphertext + iv
# 接收方
session_key = sm2_crypt.decrypt(enc_session_key)  # SM2 解密会话密钥
cipher_sm4_dec = sm4.CryptSM4(mode=sm4.SM4_DECRYPT)
cipher_sm4_dec.set_key(session_key, iv)
plaintext = cipher_sm4_dec.crypt(ciphertext)

常见问题与深度问答

Q1:SM2 和 SM4 能否替换 RSA 与 AES?

A: 可以,且国密合规,但注意:

  • SM2 性能优于 RSA 2048,密钥更短(256位 vs 2048位)。
  • SM4 与 AES 安全性同级别(AES-128 对应 SM4-128),但 SM4 硬件加速尚未普及。
  • 迁移成本: 银行核心系统已完成替换,物联网场景建议优先选用。

Q2:SM4 的 GCM 模式为什么推荐?

A: GCM 同时提供加密与完整性校验(类似 AES-GCM),避免 CBC 模式下“密文替换/填充预言攻击”。
使用示例(需扩展 gmssl 或改用 pysmx 库):

# 伪代码示意
tag = sm4_gcm_encrypt(key, iv, aad, plaintext)  # tag 用于验签
# 解密时验证 tag 是否一致,否则返回失败

Q3:SM2 签名时为什么要提供随机数?

A: SM2 签名算法基于 ECDSA,随机数 k 必须唯一、不可预测。
若随机数重复或已知,攻击者可推导出私钥(如索尼 PS3 签名泄露事件)。
最佳实践: 使用 secrets.randbelow() 或硬件真随机数生成器(TRNG)。

Q4:如何保证 SM4 密钥的安全存储?

A:

  1. 生产环境密钥使用硬件安全模块(HSM)或密钥管理系统(KMS)。
  2. 代码中不硬编码密钥,通过环境变量或配置中心(如 etcd)注入。
  3. SM4 会话密钥仅存于内存,使用后立即 memset 清零(Python 可用 ctypes 手动清理)。

总结与最佳实践建议

  1. 合规第一: 政务云、金融系统必须使用国密,且通过 GM/T 测试。
  2. 混合加密必然: 小数据用 SM2,大数据用 SM4,二者结合。
  3. 模式选择: SM4 优先选 GCM(带认证),拒绝 ECB。
  4. 库备选方案: Python 选 gmssl(功能全但性能一般)或 pysmx(C扩展,快百倍);Java 用 BouncyCastle 国密插件。
  5. 调试技巧: 使用在线国密工具(如 gmssl.cn)验证加解密结果一致性。

行动清单:

  • [ ] 生成 SM2 密钥对,完成加密解密测试。
  • [ ] 实现 SM4-GCM 加密并验证完整性。
  • [ ] 搭建混合加密 demo,传输 10KB 数据验证性能。

掌握 SM2/SM4 不仅是技术升级,更是国家网络安全战略的基石,立即动手,让你的应用从“能用”走向“合规、安全”。

抱歉,评论功能暂时关闭!