国密算法基础:SM2、SM3、SM4 原理速通

说起国密改造,最绕不开的就是这三兄弟——SM2、SM3、SM4。很多同学刚接触时容易混淆:什么时候用 SM2?什么时候用 SM4?SM3 和 SM2 签名是什么关系?

我自己的经历就是:刚开始接手一个日志适配项目,以为只要把 AES 换成 SM4 就行,结果审计时候被指出“签名和哈希也得换”。嗯,其实它们三个是各司其职的。下面我一个一个讲清楚。

SM2 非对称加密:公钥密码,干大事的

SM2 是基于椭圆曲线(ECC)的非对称算法,密钥长度 256 位,安全强度相当于 RSA 3072 位。它的核心能力有三:密钥协商、数字签名、公钥加密。

  • 密钥协商:双方通过 SM2 交换临时公钥,各自计算出一个共享密钥。这在日志传输建立加密通道时很常用。
  • 数字签名:用私钥对消息的哈希值签名,别人用公钥验签。日志完整性保护、不可抵赖都靠它。
  • 公钥加密:直接用公钥加密小量数据(比如 SM4 的密钥),私钥解密。
个人习惯:我在做日志改造时,一般把 SM2 作为“钥匙包装器”——用 SM2 加密 SM4 会话密钥,再配合 SM3 做完整性,这样性能和安全平衡得很好。

一次项目里,我们测试发现 SM2 签名验签耗时大约是 RSA 2048 的 1.5 倍,但密钥长度只有 32 字节,非常适合日志这种元数据级场景。你想想看,每条日志带一个签名,如果签名数据太大,网络开销就压不住了。

SM3 哈希算法:摘要生成的“安全指纹”

SM3 输出 256 位(32 字节)哈希值,结构上类似 SHA-256。它的核心用途是数据完整性校验和数字签名中的摘要生成。

  1. 输入任意长度的消息;
  2. 经过填充和迭代压缩;
  3. 输出固定长度的摘要。

日志改造中,SM3 最常见的用法是对日志主体(body)计算哈希,再用 SM2 签名这个哈希。这样可以避免对大段日志直接做非对称加密,性能更好。

我曾经踩过一个坑:对空字符串做哈希时,SM3 的实现依赖于输入长度,有些 SDK 在初始化时容易漏掉长度编码。结果造成两端哈希不一致,查了两天。所以,记得在所有实现中都严格遵循 GM/T 0004-2012 填充规则。

另一个注意点:SM3 的抗碰撞性已经经过商密认证,目前没有公开碰撞。但如果你在日志里只截取前 8 字节做“短哈希”,风险就大了。我建议至少用满 32 字节,除非你能接受极低概率的误判。

SM4 对称加密:数据加密的“主力干将”

SM4 是分组密码,分组长度 128 位,密钥长度 128 位。它采用 Feistel 结构,加解密算法完全对称,实现起来非常简洁。

在实际场景里,SM4 用来加密日志中的敏感字段,比如身份证号、交易金额等。为什么不用 SM2 直接加密?因为非对称加密太慢了,SM4 的速度大约是 SM2 的 100 倍以上。所以通常的做法是:

  • 用 SM2 加密 SM4 的会话密钥(或者用 SM2 密钥协商生成);
  • 然后用 SM4 加密具体数据。
国密改造中典型的“SM2+SM3+SM4 组合拳”:SM2 做密钥交换和签名,SM3 做哈希,SM4 做批量数据加密。三者缺一不可,但职责清晰。

我在做日志格式适配时,经常需要定义加密字段的 Padding 方式。SM4 常用的有 PKCS7、Zeros 两种。我个人喜欢 PKCS7,因为能准确恢复原始长度,不会出现尾部零被误截的问题。

三者的关系与对比

下面这张表格方便你快速对比:

算法类型密钥/输出长度主要用途性能参考
SM2非对称(ECC)私钥32B, 公钥65B(未压缩)签名、密钥协商、少量加密慢(签名约5000次/秒)
SM3哈希输出32B完整性校验、摘要生成快(约200MB/s)
SM4对称(分组)密钥16B大量数据加密很快(约1GB/s)

性能数据是 C 语言实现下的参考值,Python 环境下会慢很多,但相对关系不变。实际项目中要通过压测确定配额。

核心知识体系:一图搞定

我把三大算法在国密日志改造中的协同关系画成图,方便你建立整体印象:

国密三大算法在日志改造中的协同 国密改造日志格式适配 SM2 非对称加密 密钥协商 · 数字签名 SM3 哈希算法 完整性校验 · 摘要 SM4 对称加密 数据加密 · 高效 典型组合流程 1. SM3 对日志正文计算哈希值 2. SM2 使用私钥对该哈希签名(保证完整性) 3. SM4 加密日志中敏感字段(保证机密性) 注:实际项目中三者配合使用,视场景选择。

避坑总结

  • SM2 签名时,原始消息不需要先加密:签名只保护哈希,不会泄露内容。千万别对加密后的密文签名,那样验签时没法复原。
  • SM3 的输入编码:不同 SDK 对字符串默认编码不同,统一使用 UTF-8 或指定字节数组,否则两端摘要不一致。
  • SM4 的密钥长度:必须是 16 字节,不能多不能少。有些同学拿 32 字节就直接用,结果解密全是乱码。

嗯,掌握这三把宝剑,国密改造的密码学基础就稳了。接下来的实操里,你会看到它们如何写到日志格式里。