第一章 国密算法概述:SM2、SM3、SM4、SM9 的基本原理与应用场景

要讲国密 SDK 适配,咱们得先把这四位主角认清楚——SM2、SM3、SM4、SM9。说白了,它们就是国家密码管理局推的一套密码算法标准,跟国际上的 RSA、AES、ECC 打擂台。我在好几个金融项目中都遇到过客户指定必须用国密算法,所以这块儿你早晚得碰。

1.1 国密算法到底是什么?一个快照

国密算法不是单个算法,而是一组标准,覆盖了非对称加密、对称加密、哈希、数字签名、密钥交换等。我个人习惯把它们分成两类:SM2、SM9 是公钥密码,SM4 是对称密码,SM3 是哈希函数。你想想看,一套完整的密码体系,这几样缺一不可。

下面这张图给了个全景印象,看一眼就能明白它们在密码体系里的位置。

国密算法体系一览 国密算法标准 公钥密码 对称密码 / 哈希 SM2 SM9 SM4 SM3 数字签名 / 密钥交换 / 加密 标识密码 / 无证书加密 数据加密 / 国密 TLS 完整性校验 / 数字摘要
一个实用看法:搞 Java 国密 SDK 适配时,你只需要关心这四个算法的 Java 实现是否能调通、性能是否达标。别被复杂的数学公式吓着,底层库(如 Bouncy Castle 或 GmSSL 的 Java 封装)已经把数学细节盖住了。

1.2 SM2:椭圆曲线公钥密码算法

SM2 是国密体系里的“公钥王牌”。它基于椭圆曲线密码(ECC),具体用的是两条 256 位素域曲线。你想想看,它既能做数字签名,也能做密钥交换,还能做公钥加密,一个算法顶三个活。

主要原理

  • 密钥对:私钥是一个 256 位随机大整数,公钥是椭圆曲线上的一个点。
  • 签名:SM2 签名过程使用了用户 ID 和哈希值,跟国际 ECDSA 不太一样。我曾经踩过一个坑:SM2 签名结果是多了一个 s 的杂凑变换,导致直接拿 ECDSA 验证库去验,死活验不过。
  • 加密:采用混合加密(KDF + 对称加密),输出密文比明文长不少。

典型应用场景

场景说明
数字证书国密 SSL/TLS 证书的签名和验证,替代 RSA
电子签章政务、金融系统中的合同/公文签名
密钥协商安全通信信道建立,比如国密 VPN
关键数字:SM2 签名速度大约是 SM9 的 2~3 倍,但验签比 SM9 慢一点。做高并发签名时,我一般优先考虑 SM2。

1.3 SM3:密码杂凑算法

SM3 就是个哈希函数,输出 256 位(32 字节)摘要。它的结构与 SHA-256 很像,但不是一回事。SM3 有自己的消息扩展和压缩函数,安全性经国家密码管理局评审过。

说白了,SM3 就干一件事:给你一串数据,还你一个固定长度的指纹。改掉原始数据一丁点,指纹就变得面目全非。

主要原理

  • 输入任意长度消息,输出 256 位摘要。
  • 使用 Merkle–Damgård 结构,每 512 位分组处理。
  • 比 SHA-256 多了一轮消息扩展,计算量大约多 10~15%。

典型应用场景

  • 数字签名中的消息摘要:SM2 签名之前先对消息做 SM3 哈希,再签哈希值。
  • 完整性校验:下载文件后计算 SM3 摘要,跟官方公布的比对——我在某政务项目里就用它校验安装包。
  • 口令存储(加盐):虽然 SM3 不是专门为加盐设计的,但配合随机盐可以做口令哈希。
注意:SM3 不是等长输入的。你在 Java 里调用 java.security.MessageDigest 时,如果用的是 Bouncy Castle 提供的 SM3 算法名,记得确认 provider 版本在 1.68 以上,否则可能找不到。

1.4 SM4:分组对称加密算法

SM4 是国密里的对称加密担当。它是个 128 位分组、128 位密钥的 Feistel 结构算法,跟 AES 的地位相当。你可能在项目里用过 AES,那 SM4 就是它的“国密亲戚”。

主要原理

  • 分组大小 128 位,密钥长度 128 位。
  • 32 轮非线性迭代,每轮用 S 盒进行字节替换。
  • 支持 ECB、CBC、CFB、OFB、CTR 等常见工作模式,也支持 PKCS#7 填充。

典型应用场景

场景常见做法
国密 TLS/SSLSM4-SM3 密码套件(如 ECC-SM2-SM4-SM3)
数据库字段加密用 SM4-CBC 加密敏感数据,密钥保存在硬件加密机中
文件加解密大数据量场景,配合 SM2 进行密钥协商,然后用 SM4 加密实际内容
我个人经验:SM4 的软件实现在现代 CPU 上速度大约 300~500 MB/s,比纯 Java 的 AES 慢一些,但比 SM2 快几个数量级。所以实际项目里,大块数据一定用 SM4 加密,SM2 只用来加密 SM4 密钥或签名。

1.5 SM9:基于身份的密码算法

SM9 是我觉得最酷的一个——它不需要证书。你想想看,传统公钥密码得先有个 CA 给你颁发证书,还要做证书链校验,多麻烦。SM9 直接拿你的标识(比如邮箱、手机号、身份证号)当公钥,私钥由密钥生成中心(KGC)分发。

它的数学基础是双线性对(Weil 对 / Tate 对),说白了比普通椭圆曲线多了一层“配对”操作,计算量更大,但功能也更强。

主要原理

  • 系统参数由 KGC 生成,包含主密钥和公开参数。
  • 用户 Bob 的私钥 = KGC 用主密钥和 Bob 的标识计算出来的。
  • Alice 可以用 Bob 的标识(例如 bob@example.com)直接加密数据,Bob 用自己的私钥解密,全程不需要证书。

典型应用场景

  • 邮件加密:发件人知道收件人邮箱就能加密,省去证书分发。
  • 物联网设备身份认证:设备 MAC 地址或序列号作为标识,KGC 预置私钥,设备出厂即具备加密能力。
  • 无证书数字签名:适合需要撤销证书中心的轻量级场景。
性能对比一览:下面这张表我用过无数次,能帮你快速判断选型。
算法类型安全强度典型速度(相对)证书依赖
SM2公钥(ECC)128 位中等(签名快,验签略慢)需要
SM3哈希128 位较快(~SHA-256的 80%~90%)无
SM4对称128 位很快(几百 MB/s)无
SM9公钥(标识)128 位慢(配对运算,约 SM2 的 1/3~1/5)无(需 KGC)
避坑指南:我曾经在一个项目中想在 Java 里直接调用 SM9 加密。结果发现 Bouncy Castle 直到 1.70 版本才正式支持 SM9,而且接口比 SM2 复杂很多。如果你要适配多语言,SM9 的 Java 实现目前只有有限的几个库可选(如 GmSSL-Java 或部分厂商 SDK),踩坑概率较高。建议先从 SM2/SM4 入手,再推 SM9。

1.6 如何选择应用组合:三个实战例子

  1. 金融数据传输:客户端用 SM2 从 KGC 获取加密后的 SM4 会话密钥,然后用 SM4-CBC 加密交易数据。服务端用 SM2 解密得到 SM4 密钥,再用 SM4 解密数据。全程 SM3 校验完整性。
  2. 电子病历签名:医生用 SM2 对 SM3 摘要签名,同时用 SM9 加密病历内容(以患者身份证号为标识),实现“签名 + 加密”双保险。
  3. 物联网固件升级:固件发布方用 SM3 计算固件摘要,然后用 SM2 签名摘要。设备内置 SM2 公钥验签,验通过后再用 SM4 解密固件内容(固件本身通过 SM4 加密传输)。