基础密码学回顾:对称加密、非对称加密、哈希、数字签名
做加密SDK审计,绕不开这几个老朋友。我见过不少开发者,接口调了半天,结果连密钥用多大、模式选错都没意识到。说白了,基础不牢,审计就是个筛子。所以这一章,我们把对称加密、非对称加密、哈希和数字签名快速过一遍,重点放在它们在实际集成时容易踩的坑上。
对称加密:AES 与 SM4
对称加密,顾名思义,加密和解密用同一把钥匙。速度快,适合大量数据的加解密。标准接口里最常见的是 AES,国密则用 SM4。我在一个跨境支付项目中,就是被要求同时支持这两套算法。
| 参数 | AES | SM4 |
|---|---|---|
| 密钥长度 | 128 / 192 / 256 bits | 128 bits(固定) |
| 分组大小 | 128 bits | 128 bits |
| 常见模式 | ECB, CBC, CTR, GCM | ECB, CBC, CTR, GCM(SM4-GCM 国标扩展) |
| 填充 | PKCS7(CBC/ECB 必须) | 同左 |
这里重点讲模式。ECB 模式——千万别在生产环境用,同一明文块会得到相同密文块,泄露模式信息。我早年做过一个安全加固项目,对方的 SDK 默认用 ECB,我直接让他们全改成 GCM。为什么?GCM 自带认证,相当于加密 + 完整性校验,一步到位。
非对称加密:RSA 与 SM2
非对称加密使用密钥对——公钥加密,私钥解密。主要用于密钥协商、数字签名和少量数据加密。RSA 是老牌选手,SM2 则是国密局基于椭圆曲线(ECC)的产物。
| 对比项 | RSA | SM2 |
|---|---|---|
| 密钥长度 | 1024/2048/4096 bits | 256 bits(曲线长度) |
| 安全强度 | 2048 bits ≈ 112 bits 安全 | 256 bits ≈ 128 bits 安全 |
| 性能 | 慢(特别是私钥操作) | 快(同安全强度下约 5-10 倍) |
| 主要用途 | 加密小数据、数字签名 | 加密、签名、密钥交换 |
我习惯在审计集成时优先推荐 SM2,原因很简单:密钥更短,性能更高,而且国产合规。但 RSA 在存量系统里仍然广泛存在,所以两套都得会。
哈希:SHA256 与 SM3
哈希函数把任意长度的数据变成固定长度的摘要。不可逆、抗碰撞。SHA256 是国际标准,SM3 是国标。两者在审计接口中主要用于:完整性校验、密钥派生、消息认证码(HMAC)的基础。
| 算法 | 输出长度 | 安全强度 | 使用场景 |
|---|---|---|---|
| SHA256 | 256 bits | 128 bits | 通用完整性校验 |
| SM3 | 256 bits | 128 bits | 国密标准,合规要求 |
你想想看,如果通信双方验证数据完整性,只传一个哈希值,中途被篡改怎么办?所以审计接口通常要求用 HMAC,也就是带密钥的哈希。我曾经在审计中发现一个系统直接用 SHA256 裸哈希做校验——攻击者只要能改数据就能重算哈希,完全没防护。后来改成了 HMAC-SM3。
数字签名
数字签名结合了哈希和非对称加密。流程很简单:发送方对消息做哈希,再用私钥签名;接收方用公钥验签。这样既能确认来源,又能防止篡改。
在审计接口里,常见的签名算法有 RSA-SHA256、SM2-SM3。前者是 RSA 私钥签名 + SHA256 哈希,后者是 SM2 私钥签名 + SM3 哈希。
- 对请求体按字典序拼接参数(如 a=1&b=2)
- 对整个字符串做哈希(SHA256 或 SM3)
- 用私钥签名得到签名值
- 接收方同样拼接、哈希、用公钥验签
我个人体会,签名最容易出错的地方是参数拼接顺序和空值处理。比如某个字段值为空,要不要拼进去?不同 SDK 理解不同。审计时必须明确规范,否则两端对不上签名。
// 伪代码示例:SM2 签名
byte[] digest = sm3Hash(message);
byte[] signature = sm2Sign(privateKey, digest);
// 接收方
byte[] digest = sm3Hash(message);
boolean ok = sm2Verify(publicKey, digest, signature);
看完这张图你就明白了,数字签名不是独立的新算法,而是把哈希和非对称加密组合在了一起。审计的时候,你需要检查每一步的实现是否正确:哈希算法是否合规、密钥管理是否有漏洞、签名拼接规则是否一致。