4. 国密算法在接口中的角色:加密、签名、完整性校验归纳总结
我做了不少接口治理项目,跟国密算法打交道也有年头了。说实话,很多人刚开始接触国密时,容易把加密、签名、哈希混为一谈——总觉得它们都是“把数据变乱”,其实干的是完全不同的活儿。
国密算法在接口里,归根到底就三件事:保证数据不被偷看、保证数据没被篡改、证明数据是谁发的。下面我挨个拆开讲,最后再串起来看它们怎么配合的。
4.1 加密——保护数据不被偷看
加密的目的很纯粹:让不该看的人看不懂。接口传输中,如果数据明着走,中间人抓个包什么都知道了——这肯定不行。
国密加密分两种:对称加密 SM4 和 非对称加密 SM2。它们的用法差别很大,我列个表对比一下。
| 对比项 | SM4(对称) | SM2(非对称) |
|---|---|---|
| 密钥 | 双方共用一个密钥 | 一对密钥(公钥/私钥) |
| 速度 | 快(硬件加速后可达Gbps) | 慢(适合小数据量) |
| 适用场景 | 大量业务数据加密 | 密钥交换、数字信封 |
| 典型用法 | SM4-CBC/PKCS7Padding | SM2公钥加密对称密钥 |
我个人习惯:能用对称加密的地方尽量不要用非对称去硬套。有一次我见过有人直接用 SM2 加密整个大报文,结果接口响应时间从 200ms 飙到 6 秒——你想想看,非对称加密每个分组只能加密少量数据,效率摆在那。
4.2 签名——证明是你干的
加密解决了“别人看不懂”,但没解决“对方到底是谁”。签名就是用来解决这个的。
SM2 签名算法本质是:发送方用私钥对摘要签名,接收方用公钥验签。只要验签通过,就能证明这条数据是私钥持有者发的,而且中途没被改过。
# Python 示例:SM2 签名与验签(使用 pysmx 库)
from pysmx.SM2 import generate_keypair, Sign, Verify
# 生成密钥对
private_key, public_key = generate_keypair()
# 签名(假设消息为字节串)
message = b"transfer=1000&to=alice"
signature = Sign(private_key, message)
# 验签
is_valid = Verify(public_key, message, signature)
print("验签结果:", is_valid) # True or False
为什么要用签名而不是直接用加密来防伪造?
嗯,这里要区分清楚:加密是对数据本身做变换,验证方要么能解密看到原文(前提是有密钥),但无法判断数据是不是来自声称的发送者。签名则不同——它不需要隐藏数据,只需要证明“我承认这条数据是我发的”。这在实际业务中非常关键,比如金融转账接口,对方不能事后抵赖“我没发过这笔转账”。
4.3 完整性校验——数据动没动过?
完整性校验听起来跟签名有点像,但它不管“谁发的”,只管“有没有变过”。
国密里的完整性校验就用 SM3 哈希算法。哈希是一个单向函数,输入任意长度,输出固定 256 位的摘要。哪怕原文只改了一个比特,摘要都会完全不同。
| 特性 | SM3 哈希 |
|---|---|
| 输出长度 | 256 位(32 字节) |
| 抗碰撞性 | 强,安全性相当于 SHA-256 |
| 典型用途 | 校验数据完整性、签名前的摘要计算、HMAC-SM3 |
那什么时候只用 SM3 就够了?
举个例子:你向外提供某个公开的 SDK,里面有固件更新包。你可以在发布页公布该文件的 SM3 摘要值。用户下载后自己算一遍,跟公布的比对—如果一致,说明文件没被篡改。这个场景不需要签名,因为你是公开的,不需要证明“是你发的”,用户只关心文件本身有没有被动过。
但在接口通信中,SM3 通常是跟签名绑在一起的。我习惯的做法:先把请求体的所有字段按字典序拼接,算 SM3,然后把摘要放进签名内容里一起签名。接收方验签通过后,再自己算一遍 SM3 跟签名里的摘要比对,确保某些字段没有在中间被调包。
4.4 三个角色如何协同?
一个完整的接口安全设计,通常不是只用其中一种。拿最常见的“请求加签+数据加密”场景来说:
- 发送方: 用 SM3 对请求体算出摘要,
- 用 SM2 私钥对摘要签名,
- 用 SM4 对称密钥加密整个请求体 + 签名,
- 用接收方的 SM2 公钥加密 SM4 密钥,一起发过去。
- 接收方: 先用自己 SM2 私钥解密得到 SM4 密钥,
- 再用 SM4 密钥解密得到原文和签名,
- 然后用发送方 SM2 公钥验签,
- 最后自己算一遍 SM3 比对摘要是否一致。
你看,加密、签名、哈希全用上了。这叫“层层防护”。
但也别觉得每个接口都得这么复杂。我根据接口敏感程度,一般分成三个等级:
等级二(中等敏感): SM3 + SM2 签名,数据明传。
等级三(高敏感): SM4 加密 + SM2 签名 + SM3 摘要,全套上。
拿我自己做过的支付接口来说,必须走等级三。因为资金数据一旦泄露或篡改,后果非常严重。而一些内部配置接口,等级一完全够用——没必要为了“国密”二字盲目堆砌所有算法,增加接口延迟和开发成本。
4.5 避坑清单
- 签名和加密的顺序不能反。 应该先签名后加密。如果先加密再签名,别人拿到你的签名后并不知道原始数据是什么,但验证者需要先解密才能验签,逻辑上就拧巴了。
- SM3 摘要不要直接当签名用。 你想想看,如果只传摘要,中间人截获后完全可以自己改数据、重算摘要,接收方根本无法判断谁改的。签名需要私钥参与,才具有不可否认性。
- 密钥管理比算法本身更重要。 我曾经遇到过客户,SM4 密钥硬编码在代码里,还忘了切环境——测试和线上用同一个密钥。这等于锁没坏,但钥匙挂在门口。
总结一下:国密三件套——加密负责“藏”,签名负责“认”,哈希负责“查”。在接口治理中,理解它们的定位和配合原则,比死记硬背算法参数重要得多。