密码学基础回顾:对称/非对称加密、哈希、签名、密钥交换
密码学,说白了就是让不该看的人看不懂,让该看的人能验证真伪。
这套基础是PKCS#11的根基。你想想看,要是连这些概念都搞混,后面做接口集成肯定踩坑。我个人习惯是把密码学工具分为四类:加密、哈希、签名、密钥交换。今天咱们逐个拆开聊。
对称加密:一把钥匙开一把锁
对称加密用同一个密钥做加密和解密。速度快,适合批量数据。我在项目中遇到过一个大坑:业务方想用AES-256加密几TB的日志,结果没算好性能开销,直接拖垮了数据库的IO。后来我们换成了AES-128-GCM,性能提升了一倍,安全性也没降多少。
核心要点
- AES:目前最主流的对称算法。密钥长度有128、192、256位。
- 模式:ECB(别用)、CBC(常用但需要IV)、GCM(推荐,自带认证)。
- 流密码 vs 块密码:RC4是流密码,AES是块密码(128位一块)。
嗯,这里要注意ECB模式。同样的明文块会产生同样的密文块。举个例子,给一张企鹅图片用ECB加密,加密后还能看到企鹅轮廓。这哪叫加密啊?我建议项目里默认选GCM,除非你有特殊理由。
# Python 示例:AES-GCM 加密
from Crypto.Cipher import AES
import os
key = os.urandom(32) # 256 位密钥
nonce = os.urandom(12) # 96 位 nonce(推荐)
cipher = AES.new(key, AES.MODE_GCM, nonce=nonce)
plaintext = b"This is sensitive data"
ciphertext, tag = cipher.encrypt_and_digest(plaintext)
# 解密时,需要 key, nonce, ciphertext, tag
cipher_dec = AES.new(key, AES.MODE_GCM, nonce=nonce)
data = cipher_dec.decrypt_and_verify(ciphertext, tag)
非对称加密:公钥私钥不分离
非对称加密用一对钥匙:公钥加密,私钥解密。公钥可以公开,私钥必须保密。速度慢,但解决了密钥分发问题。
我记得刚接触PKCS#11时,最困惑的就是密钥标签和密钥对的关联关系。每个密钥对都有一个唯一的句柄,私钥句柄通常不能直接导出,而公钥句柄可以。这个设计其实很合理——私钥一旦离开硬件安全模块,安全性就没了保证。
实践建议
非对称加密不要用来加密大文件。它适合加密对称密钥(比如AES密钥),或者用于数字信封。我见过一些新手直接用RSA加密几MB的文件,结果性能惨不忍睹。
| 算法 | 密钥长度 | 安全强度 | 典型用途 |
|---|---|---|---|
| RSA | 2048/4096 | 112/128位 | 加密小数据、签名 |
| ECC | 256/384 | 128/192位 | 移动设备、签名、密钥交换 |
| SM2 | 256 | 128位 | 国密标准 |
哈希:不可逆的指纹
哈希函数把任意长度的数据变成固定长度的摘要。它不可逆——你不能从摘要反推出原文。两个关键属性:抗碰撞性(很难找到两个不同输入得到相同输出)和单向性。
避坑指南
我曾经被MD5坑过一次。当时做文件完整性校验,项目里用了MD5。结果发现攻击者可以在不改变MD5的情况下篡改文件(因为存在已知碰撞)。从那以后,任何新项目我都只推SHA-256或更高。
记住:MD5和SHA-1已经不安全了。现在最低标准是SHA-256。
哈希还有一个重要变种:HMAC(基于哈希的消息认证码)。它加了一把密钥,让只有知道密钥的人才能验证哈希的正确性。我建议你在API签名场景里优先用HMAC,而不是单纯的哈希。
签名:证明你是谁
数字签名是哈希+非对称加密的组合。流程是这样的:
- 对消息做哈希,得到摘要
- 用私钥加密这个摘要,得到签名
- 验证时,用公钥解密签名,得到摘要A;再对消息做哈希得到摘要B
- 如果A == B,说明消息没被篡改,而且确实是私钥持有者签的
你想想看,这个设计多巧妙。签名同时保证了真实性(确实是这个人签的)和完整性(消息没被改)。我在做硬件安全模块集成时,最常遇到的签名算法是RSA-PSS和ECDSA。RSA-PSS比PKCS#1 v1.5更安全,但兼容性稍差些。
密钥交换:怎么安全地拿到对方的公钥?
没有密钥交换,所有加密都无从谈起。最经典的协议是Diffie-Hellman (DH)。它能让你和另一个人在不安全的信道上,共同协商出一个只有你俩知道的对称密钥。
DH的问题是:它不验证身份。你无法确定你是在跟谁交换密钥。这就是中间人攻击的根源。解决方法是加入签名,或者用ECDH(椭圆曲线版本的DH),再配合证书链验证。
个人经验
在PKCS#11环境下做ECDH时,一定要检查私钥的访问控制属性。有一次我忘了设置CKA_SENSITIVE和CKA_EXTRACTABLE,结果私钥被意外导出,差点出了安全事故。现在我的习惯是:生成密钥时立刻锁定这些属性。
四大机制的对比
| 机制 | 密钥类型 | 可逆性 | 性能 | 主要用途 |
|---|---|---|---|---|
| 对称加密 | 对称密钥 | 可逆 | 快 | 加密大量数据 |
| 非对称加密 | 公钥/私钥对 | 可逆 | 慢 | 加密对称密钥、签名、数字信封 |
| 哈希 | 无密钥 | 不可逆 | 快 | 完整性校验、密码存储 |
| 签名 | 私钥签名/公钥验证 | 不可逆(摘要部分) | 中等 | 身份认证、数据签名 |
这些就是密码学的基础工具。你不需要成为数学专家,但必须懂它们各自能做什么、不能做什么。后面我们做PKCS#11集成时,每一步都会用到这些概念。嗯,先把基础打牢,后面就不慌了。