2. 密码学基础复习:对称加密、非对称加密、哈希与数字签名
这一章,咱们把密码学里最核心的几个算法拉出来遛一遛。你可能会想:“都搞PKCS11了,这些基础还用复习?”
没错,我个人习惯是每碰一个新项目,先快速过一遍密码学基础。因为后面你会看到, 里的所有操作——加密、签名、密钥生成——都绕不开它们。
我见过很多开发者在接口里乱填AES模式,或者把RSA私钥当公钥传。嗯,别笑,我也犯过。所以这一章我们聊透,避坑指南也一并送上。
2.1 对称加密与AES
对称加密,说白了就是 一把钥匙开一把锁。加密和解密用同一个密钥。AES 是目前最主流的对称算法。
我在做金融加密机项目时遇到过一个问题:客户要求每笔交易用AES-256-CBC加密,但初始化向量(IV)必须固定。结果?密文模式严重,安全审计直接打回。后来我改成AES-256-GCM,用随机IV + 附加认证数据,问题才解决。
AES 关键参数
- 密钥长度:128 / 192 / 256 位,长度越长越安全。
- 工作模式:CBC(需要IV,不能并行)、GCM(支持认证,推荐)、CTR(可并行,无填充)。
- 填充方式:PKCS7(CBC默认)、NoPadding(GCM/CTR不用填充)。
| 特性 | AES-128 | AES-192 | AES-256 |
|---|---|---|---|
| 密钥长度 | 128 bit | 192 bit | 256 bit |
| 轮数 | 10 | 12 | 14 |
| 安全强度 | 高(非敏感场景) | 更高 | 最高(推荐) |
| 性能 | 最快 | 中等 | 稍慢(但软硬件均支持) |
2.2 非对称加密:RSA与ECC
非对称加密,就是一对密钥:公钥加密,私钥解密(或反过来签名)。PKCS11里,私钥永远待在内,你只能操作句柄。
RSA
RSA基于大整数分解难题。密钥长度通常2048或4096位。我最早做CA系统时用RSA 1024,后来被安全规范禁止——现在最少2048。
RSA的签名和加密是两套模式:RSA_PKCS1_PADDING 和 RSA_PKCS1_OAEP_PADDING。OAEP更安全,我建议优先选它。
ECC(椭圆曲线密码学)
ECC用更短的密钥提供同等安全强度。比如256位ECC ≈ 3072位RSA。PKCS11常用的曲线有 P-256、P-384、P-521(对应secp256r1等)。
我在移动支付项目中推广过ECC,最大的痛点不是算法,而是曲线参数协商。不同厂商的支持的曲线可能不一样,接口里必须显式指定CKA_EC_PARAMS。
| 对比项 | RSA-2048 | ECC P-256 |
|---|---|---|
| 密钥长度 | 2048 bit | 256 bit |
| 签名速度 | 慢 | 快 |
| 验签速度 | 较快 | 较慢(但整体优于RSA) |
| 推荐场景 | 兼容性优先 | 性能与带宽敏感 |
2.3 哈希函数(SHA)
哈希就是把任意长数据变成固定长度的摘要,不可逆。SHA家族目前主力是 SHA-256、SHA-3-256。
我之前有个项目用了SHA-1做文件完整性校验,结果被攻击者在两个不同文件里碰撞出相同哈希。嗯,从那以后我见SHA-1就直接标红。
CKM_SHA_1机制,改用CKM_SHA256或以上。
常用哈希算法
- SHA-256:输出32字节,安全可靠,签名前摘要的首选。
- SHA-384:48字节,适合搭配P-384曲线。
- SHA-512:64字节,更安全但慢,可配合SHA-3使用。
- SHA-3:新一代标准,固件兼容性不如SHA-2,但更抗量子(当前)。
2.4 数字签名原理
数字签名 = 哈希 + 私钥加密。你想想看,签名并不是直接加密整份文件,而是先取文件摘要,再用私钥对摘要加密,形成签名值。
验证时,接收方用同样的哈希算法计算文件摘要,然后用公钥解密签名,对比两个摘要。如果一致,就说明数据未被篡改,且签名者确实持有私钥。
我在做电子合同系统时,签名流程是典型三步:
- 调用的
C_DigestInit+C_DigestUpdate计算文件哈希。 - 用
C_SignInit+C_Sign对哈希摘要签名。 - 验签时用
C_VerifyInit+C_Verify。
CKM_RSA_PKCS_PSS会自己管理盐和哈希。你不需要手工拼接。
我曾经踩过一个坑:在调用C_Sign之前,忘了调用C_SignUpdate传入数据。结果返回CKR_DATA_LEN_RANGE。嗯,细节决定成败。
CKM_ECDSA_SHA256这种组合机制,会自己算SHA-256然后再签名。你只需要传入原始数据,不用手动哈希。
小结
这一章我们把AES、RSA/ECC、SHA和数字签名捋了一遍。你会发现,PKCS11接口就是把这些算法包装成标准函数调用。理解算法本身,才能理解为什么接口需要CKA_EC_PARAMS、为什么签名需要CKM_RSA_PKCS_PSS。