1. 国密算法概述:SM2/SM3/SM4 简介与行业应用场景归纳总结
1.1 我们为什么要学习国密?
先问个问题:为什么非要用国密?直接用国际通用的RSA、AES、SHA-256不行吗? 技术上当然可以。但很多行业,尤其是政府和金融领域,有硬性合规要求。说白了,这是入场券。我记得前几年有个项目,对方明确要求所有数据传输必须使用SM4加密,签名必须用SM2。你不支持?对不起,连投标资格都没有。 所以,学习国密不只是技术选择,更是业务刚需。1.2 三个核心算法速览
国密标准包含的算法不少,但我们日常开发打交道最多的就是SM2、SM3、SM4。我把它们的基本信息整理成了下表,方便你对照记忆。| 算法名称 | 类型 | 对标国际算法 | 核心用途 |
|---|---|---|---|
| SM2 | 非对称加密 / 数字签名 | RSA / ECDSA | 密钥交换、数字签名、数据加密 |
| SM3 | 密码杂凑函数 | SHA-256 | 完整性校验、摘要生成、HMAC |
| SM4 | 对称分组密码 | AES | 数据批量加密 |
一个小经验:性能敏感的场景,优先用SM4。SM2非对称运算很慢。我做过压测,SM2的签名速度只有SM4加密的几十分之一。别把SM2当主力对称加密来用。
1.3 SM2:椭圆曲线上的门神
SM2是一个基于椭圆曲线密码学的算法族。它包含三个子功能:数字签名、密钥交换、公钥加密。 * **数字签名**:用于证明“你是谁”以及“消息是你发的”。应用在身份认证、合同签署。 * **密钥交换**:通信双方在不安全的信道上协商出一个共享密钥。注意,它和RSA不同,SM2的密钥交换协议更复杂,也包含了双方身份认证。 * **公钥加密**:用对方公钥加密,只有对方私钥能解。这个在国标里虽然定义了,但实际项目里用得最少。为啥?因为SM4效率高得多,大家习惯用SM2交换一个临时密钥,再用SM4去加密正文。 我个人习惯把SM2看作是“钥匙管理员”,只负责管理最核心的密钥,不负责搬砖(加密大量数据)。1.4 SM3:不可逆的指纹
SM3算法输出一个256位(32字节)的杂凑值。它的作用就是给任意数据打上一个唯一的“指纹”。 * 你下载一个文件,厂家提供SM3摘要,你本地算一遍,对上号就说明文件没被篡改。 * 你设置的密码,系统不会存明文,而是存SM3哈希值。 SM3的安全强度对标SHA-256,但它的设计更侧重于在国产硬件平台(比如龙芯、飞腾)上能跑得更快。我在项目中遇到过,某些加密芯片对SM3有硬件加速,SM3的运算基本是零开销。
避坑指南:千万不要对SM3的结果做二次哈希或者截断来“增强安全性”。这在密码学上通常不会增加安全性,反而可能引入新的碰撞风险。我就见过有人把SM3结果截断成16字节当用,结果导致碰撞概率急剧上升。
1.5 SM4:低调的速度担当
SM4是对称加密算法,密钥长度128位,分组长度128位。它的运算速度非常快,适合加密大量数据。 SM4通常有几种工作模式: * **ECB**:电子密码本模式。简单粗暴,但相同明文会生成相同密文,不安全。**不建议使用**。 * **CBC**:密码块链接模式。需要初始化向量(IV),能掩盖明文模式。最常用。 * **GCM** / **CCM**:带认证的加密模式。不仅能加密,还能保证数据完整性。**强烈推荐**。 在实际项目里,我首选SM4-GCM模式。它一步到位,解决了加密和防篡改两个问题,省心。1.6 行业应用场景图谱
下面这张图,你可以看作是国密算法的“使用说明书”。它展示了在不同安全层级,对应应该使用哪种算法。1.7 不同代码库的调用差异切入点
好了,基础概念说完了。现在聊聊咱们这门课的核心——调用差异。 市面上主流的Go语言国密SDK,我接触下来,主要有这几块: 1. **GMSSL-Go**: GmSSL项目的Go语言封装。它的一大特点是接口模仿OpenSSL,对C语言背景的开发者比较友好。 2. **tjfoc/gmsm**: 比较早期、也比较常用的一个库。接口设计比较直接,但历史包袱重,有些API已经过时了。 3. **官方新生态**: 近两年,一些大厂或组织开始基于Go标准库的`crypto`接口风格重构国密库。这是个好趋势,接口更统一,学习成本更低。 这些库之间的差异,主要体现在以下几个方面。这也是后面我们每一节课会逐一攻克的难点: * **密钥的生成与格式**: 用`*big.Int`还是用`[]byte`?私钥怎么序列化成PEM?不同库的标准不同。 * **加解密函数签名**: 参数顺序、返回值的类型、错误码定义,差异很大。 * **性能表现**: 有些库对SM2的`Sign`做了优化,有的对SM4的`GCM`模式有专门实现。我做过基准测试,同一个算法在不同库里的性能能差20%。 * **异步与并发安全性**: 有些库的对象是线程安全的,有些不是(比如`SM2PrivateKey`对象是否需要加锁)。这是个容易踩坑的点。
一个忠告:不要轻易在同一个项目里混用不同的国密库。密钥格式、编解码方式如果不一致,会导致秘而不解、验签失败的严重问题。我见过一个团队,前端用了一个SM2库算签名,后端用另一个库验,搞了三天才发现是签名格式编码问题。