第1章 密码学基础回顾
说实话,每次带新人做 PKCS#11 项目,我最怕的不是代码写不好,而是密码学概念理解偏了。你想想看,HSM 就是做密码运算的硬件,要是连对称加密、非对称加密这些基本东西都搞混,后面调接口肯定会踩坑。所以我习惯在正式讲标准之前,先花一章把地基夯实。
1.1 对称加密——一把钥匙开一把锁
对称加密,说白了就是加密和解密用同一个密钥。你在网上买东西时,服务器和你之间那层 HTTPS 握手之后,其实就会用对称加密来传输实际数据。为什么?因为快啊!
我个人在项目中遇到过一个大坑:某个系统里 AES 用了 CBC 模式,每次加密都忘了重新生成 IV,结果密文开头总是一样,攻击者很容易看出来你发的是重复的请求头。嗯,从那以后我写任何对称加密代码都会先检查 IV 是不是随机且唯一的。
| 算法 | 密钥长度(位) | 典型应用 |
|---|---|---|
| AES | 128 / 192 / 256 | 文件加密、VPN、HSM 内部数据保护 |
| SM4 | 128 | 国密标准、金融芯片 |
| 3DES | 112 / 168 | 老旧系统兼容(建议废弃) |
CKA_SENSITIVE 属性,一旦生成,谁也别想 read 出来。
1.2 非对称加密——双钥体系解决信任问题
非对称加密用一对钥匙:公钥公开,私钥自己藏着。你用我的公钥加密,只有我的私钥能解开;反过来我用私钥签名,大家用公钥验签。
我记得刚做密码卡驱动的时候,遇到一个需求:需要把一段 4KB 的数据用 RSA 公钥加密后送过去。RSA 最大加密长度受模长限制,当时我硬塞了 4KB 数据进去,结果调用 C_Encrypt 直接返回 CKR_DATA_LEN_RANGE。后来才搞清楚——非对称加密不适合大批量数据,实际方案应该是:把对称密钥用 RSA 加密传过去,然后双方用这个对称密钥做后续数据加密。
CKM_RSA_PKCS_OAEP 等机制来包装密钥。
- RSA:基于大整数分解,常用 2048/4096 位,签名和加密都可以做。
- ECC:基于椭圆曲线离散对数,256 位 ECC 安全性约等于 3072 位 RSA,密钥小、运算快。
- SM2:国密椭圆曲线算法,我的一个银行项目里替换 RSA 时就是它。
1.3 哈希算法——数据指纹,不可逆
哈希函数把任意输入变成固定长度输出,像「指纹」一样。你改一个比特,整个摘要面目全非。哈希不是加密——不可以解密,所以别问我「怎么把哈希值还原成原文」这种问题。
我曾经帮一个团队排查过哈希碰撞漏洞:他们用 SHA-1 做软件完整性验证,结果内部测试时意外发现两个不同的 DLL 居然算出相同的 SHA-1 值。虽然概率极低,但工业级场景不能赌。后来我把所有校验都换成了 SHA-256。
| 算法 | 摘要长度(位) | 安全状态 |
|---|---|---|
| SHA-256 | 256 | 推荐,广泛用于证书签名 |
| SHA-384 | 384 | 更保守的选择 |
| SM3 | 256 | 国密标准,与 SHA-256 等价 |
| SHA-1 | 160 | 已证明可碰撞,不应使用 |
C_DigestUpdate 就是干这个的。
1.4 数字签名——用私钥给数据「盖章」
签名 = 先对数据做哈希,再用自己的私钥加密那个哈希值。别人拿到数据、签名和你的公钥,算一遍哈希,再用公钥解密签名,两个哈希值一样——那就说明数据没被改过,而且确实是你签的。
我记得有一次调试 PKCS#11 签名接口,签出来的值长度总是 256 字节,但我的 RSA 密钥是 2048 位的,按理说签名结果就是 256 字节,没问题。可对方要求格式是 DER 编码的 RSASSA-PSS,结果我直接送了裸签名值,接不上去。嗯,这里要注意——PKCS#11 签名输出格式完全取决于你选择的机制,不是简单「丢进去一个签名值」就行。
1.5 数字证书——把公钥和身份绑定
光有公钥你不知道是谁的。证书就是由权威机构(CA)把公钥、持有人信息、有效期、用途等打包,再用 CA 的私钥签个名。你拿到证书,用 CA 的公钥验一下签名,就能信任这个公钥确实属于某人。
X.509 证书是最常见的格式。你打开一个 HTTPS 网站,浏览器就是靠证书链验证服务器身份的。HSM 里存储的多是加密机证书、设备证书,用来做双向 TLS 或签名验签。
C_FindObjects 可以按照证书主题、签发者、序列号等属性搜索证书。我习惯在初始化时先遍历 HSM 里所有证书,找个缓存存起来,后面需要时不用反复查。
1.6 本章知识体系总览
下面这张图把今天讲到的几个基础概念串起来,你一看就能明白它们之间如何组合使用。我画这张图时特意把对称加密、非对称加密、哈希、签名和证书放在同一个流程里——因为实际 HSM 应用场景中,这些技术经常协同工作。