SM2 加密用在哪
SM2 是基于椭圆曲线的国密公钥算法,标准中同时规定了数字签名、密钥交换与公钥加密三类用法。公钥加密典型用途是保护会话密钥或小段敏感数据:用对方公钥加密一个随机生成的对称密钥,再用 SM4 之类的对称算法加密业务数据,这就是信封结构。它的实际难点不在算法本身,而在密文格式的互操作——不同实现的分量顺序与编码约定不同,跨系统对接时必须先对齐格式,否则解密直接失败。
基本信息
| 标准 | GB/T 32918 系列(第 4 部分为公钥加密算法) |
|---|---|
| 密钥长度 | 256 位,公钥为 64 字节点坐标(未压缩编码时带 04 前缀共 65 字节) |
| 密文构成 | C1(椭圆曲线点)+ C3(摘要值,32 字节)+ C2(与明文等长的加密数据) |
| 国标顺序 | C1‖C3‖C2 |
| 常见库 | OpenSSL(1.1.1 起支持 SM2)、GmSSL、Python gmssl、各语言国密 SDK |
| 适用长度 | 适合加密密钥等小块数据,不适合直接加密大文件 |
Python(gmssl)示例
Python(gmssl)示例
from gmssl import sm2
# 公私钥均为十六进制字符串(私钥 64 位十六进制,公钥 128 位)
crypt = sm2.CryptSM2(public_key=pub_hex, private_key=priv_hex)
ct = crypt.encrypt(b"session-key-01") # 加密,返回 bytes 密文
pt = crypt.decrypt(ct) # 解密,注意输入类型要与实现约定一致
assert pt == b"session-key-01" # 自测:解密结果与原文一致
# 互操作注意:不同库/版本的分量顺序(C1C3C2 或 C1C2C3)、
# C1 是否带 04 前缀、是否输出十六进制字符串都可能不同,
# 对接前先确认对方约定,必要时按约定做顺序转换与补/去前缀互操作检查项
| 检查项 | 可能差异 | 处理方式 |
|---|---|---|
| 分量顺序 | C1C3C2(国标)与 C1C2C3(部分库默认) | 明确约定并做转换,写入接口文档 |
| C1 编码 | 是否带未压缩点前缀 04 | 按对方约定补齐或截去,长度校验放在解密前 |
| 输出编码 | 原始字节数组与十六进制字符串 | 传输层统一为 Base64 或十六进制并写进接口说明 |
| KDF 参数 | 标准实现应使用 SM3 派生,参数不可自定义 | 不自造派生函数,否则仅在本系统内能解开 |
| 密钥用途 | 加密密钥对与签名密钥对混用 | 按用途分设密钥对,避免一处泄露影响两类操作 |
加密前必须与对方核对密文顺序与编码约定,否则解密失败;这类问题在联调阶段表现为「同样的库、同样的密钥却解不开」,排查成本很高。建议把约定写进接口文档并保留一组互通测试向量。
SM2 加密依赖随机数 k:随机质量不足会导致密钥可推导。使用成熟库的默认随机源,不要自行拼接时间戳或计数器作为随机数。