密码学基础回顾:对称加密、非对称加密、哈希、数字签名原理
做 HSM 签名验签接口,说到底就是跟这四个密码学“老伙计”打交道。我个人习惯先把它们的关系理清楚——不是孤立背概念,而是理解它们怎么配合。今天就从实战角度,带你把它们串一遍。
对称加密:一把钥匙开一把锁
对称加密最直观。发送方和接收方共用同一个密钥,加密解密都用它。速度快、效率高,适合大量数据加密。我在项目中遇到过用 AES-256 加密数据库中的敏感字段,吞吐量比公钥方案快两个数量级。
| 算法 | 密钥长度 | 典型场景 |
|---|---|---|
| AES | 128/192/256 bit | 文件加密、VPN 数据通道 |
| SM4 | 128 bit | 国产商用密码,金融系统 |
| DES | 56 bit | 已淘汰,别用了 |
我曾经帮一个客户排查签名速度慢的问题,发现他们居然用 RSA 加密整个 10MB 文件……嗯,这是典型的设计失误。对称加密才是量大管饱的选择。
非对称加密:公钥私钥两把锁
非对称加密用一对密钥:公钥公开,私钥自己藏好。公钥加密、私钥解密,或者反过来签名。核心优势是解决密钥分发难题。不过速度比对称加密慢好几个数量级,所以实战中通常用它加密对称密钥,再用对称密钥加密业务数据。
举个例子:你收到一个来自银行服务器的消息,用银行公钥加密后只有银行掌握私钥能解密。反过来,银行用私钥签名的数据,任何持有公钥的人都能验证来源。
哈希(Hash):消息的“指纹”
哈希函数能把任意长度数据压缩成固定长度的摘要。单向性——从摘要反推原始数据几乎不可能。碰撞概率极低。我用 SHA-256 做文件完整性校验,一旦检测到哪怕一个字节改动,摘要都会变得面目全非。
你想想看,数字签名为什么需要哈希?因为直接用私钥加密长消息太慢,而且存在理论攻击面。先哈希,再把摘要签名,既快又安全。
| 哈希算法 | 摘要长度 | 安全强度 |
|---|---|---|
| SHA-256 | 256 bit | 高(推荐) |
| SHA-3 | 可配置 | 高 |
| MD5 | 128 bit | 已破解,严禁使用 |
数字签名:哈希 + 非对称加密的组合拳
数字签名就是用私钥对消息的哈希值进行加密(实际上是签名算法)。验证时用公钥解密摘要,再与重新计算的哈希对比。如果一致,证明消息未被篡改且来源可信。
核心流程(我习惯把它分成两步):
- 签名方:原文 → 哈希 → 摘要 → 私钥签名 → 签名值(附在原文后发送)
- 验签方:原文 + 签名值 → 公钥解密签名 → 得到摘要A;原文重新哈希 → 得到摘要B;比较A与B。
我在对接国密 SM2 签名时,发现很多开发者混淆了“哈希算法”和“签名算法”。实际上签名算法内部已经包含了哈希这一步,但接口参数要求显式传入哈希结果——这是最容易被坑的地方。
避坑提示:HSM 签名字段通常要求先对原文做哈希,再调用签名 API。不要传入原文本身,否则 HSM 内部帮你哈希一遍,你自己又哈希一遍,导致签名值错误。我曾经因为这个低级 bug 查了一天日志……
四者关系一览
下面这张图概括了它们如何在一次数字签名场景里协作。
实际接口调用的内存布局
如果你只记理论,写代码时会懵。我建议你把签名/验签接口的输入输出数据布局记清楚:
// 签名接口(以 PKCS#11 C_Sign 为例)
CK_BYTE data[256]; // 原文(或哈希值,视算法而定)
CK_BYTE signature[64]; // 签名值(长度因算法而异)
CK_ULONG sigLen = sizeof(signature);
C_SignInit(hSession, &mechanism, hPrivateKey);
C_Sign(hSession, data, 256, signature, &sigLen);
// 验签接口
C_VerifyInit(hSession, &mechanism, hPublicKey);
C_Verify(hSession, data, 256, signature, sigLen); // 返回 CKR_OK 则通过
注意:很多 HSM 要求 mechanism 里指定哈希算法,比如 CKM_SHA256_RSA_PKCS。别传错类型,否则返回 CKR_MECHANISM_INVALID。
常见的误解与纠正
- 对称加密比非对称加密“弱”——不对。AES-256 的安全强度远高于 RSA-2048,只是密钥管理麻烦。HSM 里常用对称加密做数据加密,非对称做密钥封装和签名。
- 哈希就是加密——哈希不可逆,加密可逆。别把 MD5/SHA 当密码存,那是固定长度的摘要,不是加密。
- 数字签名等于加密——签名用私钥,加密用公钥。虽然 RSA 签名在数学上跟加密操作类似,但目的和协议完全不同。签名不隐藏原文,只提供认证和完整性。
一句话总结:你在 HSM 上配置签名任务时,核心流程就是“哈希摘要是原料,私钥签名是加工,公钥验签是质检”。理解了这个,接口调用的参数该填什么,心里就有底了。