1. 国密算法概述:SM2/SM3/SM4 算法原理及应用场景简介
各位同行好,咱们直接进入正题。国密算法(商用密码算法)是国家密码管理局发布的行业标准,这几年在金融系统里几乎是绕不过去的坎。我最早接触国密改造是在一家股份制银行的网银项目里,当时客户要求全部替换国际算法,说实话心里挺没底的——SM2、SM3、SM4 这三兄弟到底怎么用?跟 RSA、AES 比有什么坑?今天我把这些年踩过的坑和总结的经验倒出来,希望能帮大家少吃点亏。
1.1 国密算法全家桶
国密算法其实不止三个,但金融场景下最常打交道的就是 SM2、SM3、SM4。你可以把它们类比成国际算法里的公钥、哈希和对称加密——SM2 对标 ECC/RSA,SM3 对标 SHA-256,SM4 对标 AES。
我习惯用一个表格来记它们的关键参数,这样好对比:
| 算法 | 类型 | 密钥长度 | 分组/输出长度 | 对标国际算法 | 核心安全依赖 |
|---|---|---|---|---|---|
| SM2 | 公钥密码(椭圆曲线) | 256 位(私钥) | 公钥 512 位 | RSA-2048 / ECC P-256 | ECC 离散对数难题 |
| SM3 | 密码哈希 | — | 256 位摘要 | SHA-256 | 抗碰撞、原像稳固 |
| SM4 | 对称分组密码 | 128 位 | 128 位分组 | AES-128 | S 盒扩散 + 32 轮非线性 |
嗯,这些参数一定要记牢。我遇到过不少开发把 SM4 和 SM2 的密钥长度搞混,导致对接时验签死活不过,后来发现是密钥长度传错了——128 位 SM4 密钥和 256 位 SM2 私钥差了一倍,多写一个 0 就出事了。
1.2 SM2:国产公钥加密与签名
SM2 是国家密码管理局发布的椭圆曲线公钥密码算法,标准文件是 GM/T 0003-2012。它的核心是 256 位素域上的椭圆曲线,比 RSA 的同等安全强度更省空间——同样 128 位安全级别,RSA 需要 3072 位密钥,SM2 只要 256 位。
SM2 能做三件事:
- 密钥协商:双方交换临时密钥,生成会话密钥(类似 ECDH)
- 数字签名:对消息或哈希值做签名,验证身份和完整性
- 公钥加密:用接收方公钥加密消息,只有对应私钥能解
我记得在证券行情传输项目里,SM2 加密的报文长度会膨胀——因为公钥加密时做了 KDF 和散列,一个 128 字节的明文可能变成 256 字节的密文。这一点在改造报文协议时容易被忽略,很多人按 RSA 的分块方式去切,结果解密失败。
04 || X坐标(32字节) || Y坐标(32字节) || 密文(变长),解密端必须完整拼接这四个部分。我曾经接手过一个项目,对方把坐标单独存了,解密时找不到 K 点,折腾了两天才发现是序列化问题。
1.3 SM3:密码杂凑算法
SM3 就是哈希算法,把任意长度的消息压缩成 256 位摘要。它跟 SM2 配合使用——签名时先对消息做 SM3 哈希,再对哈希值做 SM2 签名。这跟 ECDSA + SHA-256 的套路是一样的。
SM3 的算法结构是 Merkle-Damgård 迭代,消息分组 512 位,输出 256 位。它内部用了 64 轮压缩函数,比 SHA-256 的 64 轮还多了 16 条消息字扩展。说白了,它的设计更保守,安全余量其实比 SHA-256 还高一点点。
我测试过 SM3 的性能——在 Intel Xeon 上大概 600 MB/s,跟 SHA-256 差不多(700 MB/s),不存在“国密就是慢”的刻板印象。但要注意,SM3 的 C 实现里字节序是 Big-Endian,跟 x86 的 Little-Endian 不一样,移植时如果不转字节序,哈希值会完全错掉。我在嵌入式 MIPS 平台上栽过这个跟头,排查了一天。
// SM3 示例:计算 "SM3" 的哈希值(结果片段)
input: 53 4D 33
output: 60 3F C7 B9 ... (32 字节)
1.4 SM4:对称分组加密
SM4 是 128 位分组的对称密码,密钥 128 位,轮数 32 轮。它的设计思路类似 AES,但内部用的是 非线性 S 盒 + 线性变换 L。SM4 的 S 盒只有 8×8 位,比 AES 的 16×16 位小,所以查表实现更轻量,适合物联网和金融终端。
SM4 有四种工作模式,跟 AES 完全一样:
- ECB:不安全,别用。我见过某支付 APP 用 ECB 加密银行卡号,被密文重复暴露了卡号规律。
- CBC:需要初始化向量 IV,每次加密随机生成。金融对账单常用 CBC 模式。
- CFB / OFB:流模式,适合加密长度不固定的数据。
- CTR:并行加密,硬件友好,性能最佳。我推荐金融批量加密用 CTR。
SM4 的加解密完全对称——轮密钥顺序正好相反。你可以用一个算法实现加解密,只要改变轮密钥的输入方向就行。这点比 AES 的加解密结构不一样要简单。
1.5 国密算法在金融场景中的典型搭配
在真实金融系统里,你很少单用一个算法,一般都是组合使用。我总结了几种常见模式:
- 签名验签链:SM2 签名 → SM3 哈希验证 → SM2 验签。用于交易报文的防篡改和防抵赖。
- 加密通信会话:SM2 密钥协商 → 协商出 SM4 会话密钥 → SM4 加密业务数据。比如银企直连 TLS 国密套件。
- 数据完整性校验:直接 SM3 哈希 + 时间戳,用于日志或对账文件的完整性保护。
举个具体例子:我曾经改造过一个银行核心系统的加密机接口,原来用的是 RSA + DES + SHA-1,要求全部替换为国密。最终的方案是:
- 签名:SM2(305 字节签名,代替 256 字节 RSA)
- 加密:SM4-CBC(128 位密钥,代替 56 位 DES)
- 哈希:SM3(256 位输出,代替 160 位 SHA-1)
改造后签名长度从 256 字节变成 305 字节(多了 19%),网络传输稍微变慢,但安全强度提升了好几个数量级。加密速度从 DES 的 50 MB/s 提升到 SM4 的 180 MB/s(硬件加速前)。总体效果是可以接受的。
1.6 知识体系总览图
下面这张 SVGSVG 图概括了本章的核心知识点之间的关系,大家先扫一眼,后面每节都会对应展开。
1.7 一点个人感悟
国密改造不是简单的算法替换。我做过十几个金融项目,总结出三条铁律:
- 测试向量是命根子——SM4 和 SM2 都有官方的测试例子,改完算法先把测试向量跑通,不然对接时全是冤枉路。
- 密钥格式坑最多——SM2 的公钥是 04+XY(65 字节),私钥是 32 字节大整数。不同平台 DER 编码、PEM 格式可能不一样,建议统一用
ASN.1 DER序列化。 - 性能瓶颈在签名——SM2 签名运算大约 0.5ms~1ms(普通 CPU),SM4 加密只有几个微秒。如果要做每秒几万笔的交易,SM2 签名是主要瓶颈,可以考虑硬件密码卡加速。
我到现在还保留着刚入行时犯的一个错误:SM3 的字节序没做转换,哈希值跟国家标准错了一整个字节,被测试组当场打回。从那以后,我每次写国密代码都会先写一个字节序检查函数,打印出前四个字节的 hex 跟官方测试用例对比——三秒就能定位问题。
好了,第一章就在这里收个尾。SM2、SM3、SM4 的原理和场景先给大家搭个骨架,后面几章我们会深入每个算法的代码实现、密钥管理、接口封装和测试策略,尤其是金融改造中那些“文档没写但经验才知道”的坑,咱们慢慢聊。