国密算法基础:SM2、SM3、SM4 原理速通
说起国密改造,最绕不开的就是这三兄弟——SM2、SM3、SM4。很多同学刚接触时容易混淆:什么时候用 SM2?什么时候用 SM4?SM3 和 SM2 签名是什么关系?
我自己的经历就是:刚开始接手一个日志适配项目,以为只要把 AES 换成 SM4 就行,结果审计时候被指出“签名和哈希也得换”。嗯,其实它们三个是各司其职的。下面我一个一个讲清楚。
SM2 非对称加密:公钥密码,干大事的
SM2 是基于椭圆曲线(ECC)的非对称算法,密钥长度 256 位,安全强度相当于 RSA 3072 位。它的核心能力有三:密钥协商、数字签名、公钥加密。
- 密钥协商:双方通过 SM2 交换临时公钥,各自计算出一个共享密钥。这在日志传输建立加密通道时很常用。
- 数字签名:用私钥对消息的哈希值签名,别人用公钥验签。日志完整性保护、不可抵赖都靠它。
- 公钥加密:直接用公钥加密小量数据(比如 SM4 的密钥),私钥解密。
一次项目里,我们测试发现 SM2 签名验签耗时大约是 RSA 2048 的 1.5 倍,但密钥长度只有 32 字节,非常适合日志这种元数据级场景。你想想看,每条日志带一个签名,如果签名数据太大,网络开销就压不住了。
SM3 哈希算法:摘要生成的“安全指纹”
SM3 输出 256 位(32 字节)哈希值,结构上类似 SHA-256。它的核心用途是数据完整性校验和数字签名中的摘要生成。
- 输入任意长度的消息;
- 经过填充和迭代压缩;
- 输出固定长度的摘要。
日志改造中,SM3 最常见的用法是对日志主体(body)计算哈希,再用 SM2 签名这个哈希。这样可以避免对大段日志直接做非对称加密,性能更好。
另一个注意点:SM3 的抗碰撞性已经经过商密认证,目前没有公开碰撞。但如果你在日志里只截取前 8 字节做“短哈希”,风险就大了。我建议至少用满 32 字节,除非你能接受极低概率的误判。
SM4 对称加密:数据加密的“主力干将”
SM4 是分组密码,分组长度 128 位,密钥长度 128 位。它采用 Feistel 结构,加解密算法完全对称,实现起来非常简洁。
在实际场景里,SM4 用来加密日志中的敏感字段,比如身份证号、交易金额等。为什么不用 SM2 直接加密?因为非对称加密太慢了,SM4 的速度大约是 SM2 的 100 倍以上。所以通常的做法是:
- 用 SM2 加密 SM4 的会话密钥(或者用 SM2 密钥协商生成);
- 然后用 SM4 加密具体数据。
我在做日志格式适配时,经常需要定义加密字段的 Padding 方式。SM4 常用的有 PKCS7、Zeros 两种。我个人喜欢 PKCS7,因为能准确恢复原始长度,不会出现尾部零被误截的问题。
三者的关系与对比
下面这张表格方便你快速对比:
| 算法 | 类型 | 密钥/输出长度 | 主要用途 | 性能参考 |
|---|---|---|---|---|
| SM2 | 非对称(ECC) | 私钥32B, 公钥65B(未压缩) | 签名、密钥协商、少量加密 | 慢(签名约5000次/秒) |
| SM3 | 哈希 | 输出32B | 完整性校验、摘要生成 | 快(约200MB/s) |
| SM4 | 对称(分组) | 密钥16B | 大量数据加密 | 很快(约1GB/s) |
性能数据是 C 语言实现下的参考值,Python 环境下会慢很多,但相对关系不变。实际项目中要通过压测确定配额。
核心知识体系:一图搞定
我把三大算法在国密日志改造中的协同关系画成图,方便你建立整体印象:
避坑总结
- SM2 签名时,原始消息不需要先加密:签名只保护哈希,不会泄露内容。千万别对加密后的密文签名,那样验签时没法复原。
- SM3 的输入编码:不同 SDK 对字符串默认编码不同,统一使用 UTF-8 或指定字节数组,否则两端摘要不一致。
- SM4 的密钥长度:必须是 16 字节,不能多不能少。有些同学拿 32 字节就直接用,结果解密全是乱码。
嗯,掌握这三把宝剑,国密改造的密码学基础就稳了。接下来的实操里,你会看到它们如何写到日志格式里。