密码学基础:对称加密、非对称加密、哈希函数

要理解 TLS 1.3,得先搞定三个基本工具——对称加密、非对称加密、哈希函数。说白了,整个握手协议就是靠它们组装起来的。我带项目时见过不少开发者,上来就啃协议细节,结果被密钥协商绕晕。嗯,咱们先把地基打牢。

对称加密:快,但密钥怎么分?

对称加密大家应该不陌生。发送方和接收方用同一个密钥加密和解密。优势就一个字——快。硬件加速加持下,AES 跑个几十 Gbps 很轻松。但问题也明显:密钥怎么安全地交给对方?

现实中常用的对称算法是 AES(Advanced Encryption Standard)。TLS 1.3 里主要用 AES-GCM 和 ChaCha20-Poly1305,都是认证加密模式,既保密又防篡改。我踩过坑:当年一个项目里用 AES-CBC 加 HMAC,结果处理不当留了 padding oracle 漏洞,后来全改成了 GCM 模式,省心多了。

个人建议:对称加密的密钥一定要随机生成,别再拿“password123”当密钥了。我用 os.urandom(32) 生成 AES-256 密钥,每次不一样。

非对称加密:慢,但能解决密钥分发

非对称加密用一对密钥——公钥公开,私钥保密。数据用公钥加密后,只有私钥能解开。这就解决了密钥分发难题。你不用提前在双方之间共享密钥了。

TLS 1.3 握手阶段用非对称加密完成两件事:身份认证和密钥协商。证书里的公钥用于验证服务端身份,然后通过 ECDHE(椭圆曲线 Diffie-Hellman 密钥交换)协商出临时的对称密钥。我调试过一个问题:客户端的证书公钥是 RSA 2048,但协商时选了 ECDSA 签名,结果验签一直失败——算法不匹配,记住 证书和签名算法要配对。

特别注意:非对称加密性能差,绝不能用它加密大块数据。TLS 里它只用来做握手阶段的密钥交换和签名,实际数据传输还得靠对称加密。

哈希函数:不可逆的“指纹”

哈希函数把任意长数据变成固定长度的摘要。特点是单向——从摘要无法还原原文;抗碰撞——很难找到两个不同输入产生相同输出。TLS 1.3 里无处不在:握手消息的完整性校验、密钥派生、证书摘要都用到了哈希。

主流算法是 SHA-256 和 SHA-384。MD5 和 SHA-1 早就不安全了,别再用。我以前接手一个旧系统,文件完整性校验还是 MD5,同事觉得没问题。结果我模拟了一下碰撞攻击,两分钟就找到冲突文件,吓得他立刻改了 SHA-256。

# Python 哈希函数使用示例
import hashlib

data = b"TLS 1.3 handshake message"
sha256_hash = hashlib.sha256(data).hexdigest()
print(sha256_hash)  
# 输出:f4a7...(固定长度 64 字符)

三者对比:各司其职

特性 对称加密 非对称加密 哈希函数
密钥数量 1 个密钥 公钥 + 私钥 没有密钥
速度 极快(硬件加速) 慢(几百倍于对称) 很快
主要用途 批量数据加密 密钥交换、数字签名 完整性校验、密钥派生
典型算法 AES-256-GCM, ChaCha20 RSA-3072, ECDH P-256 SHA-256, SHA-384
TLS 1.3 角色 保护应用数据 握手期间认证与协商 握手完整性、PRF 计算

一张图理清关系

我把三种密码学工具在 TLS 1.3 中的协作关系画了出来。

TLS 1.3 中三种密码学工具协作示意图 对称加密 (AES-GCM) 非对称加密 (ECDHE + 签名) 哈希函数 (SHA-256) 保护应用数据加密 密钥协商 + 身份认证 握手完整性 + 密钥派生 最终产物:对称会话密钥 提供PRF
小结:TLS 1.3 用非对称加密(ECDHE + 签名)安全地协商出对称会话密钥,用哈希函数保证握手消息不被篡改,最后用对称加密高效保护应用数据。三种工具缺一不可。

实战避坑指南

  • 密钥长度别选错:对称加密至少 AES-128(推荐 AES-256);非对称 RSA 至少 3072 位,椭圆曲线至少 P-256;哈希至少 SHA-256。
  • 随机数生成器要安全:不要用 random 模块,用 secrets 或 os.urandom。我曾经见过有人用 C 的 rand() 生成 IV,结果每次重启 IV 都相同,重放攻击直接破防。
  • 不要自己实现密码算法:永远用经过审计的库,比如 Python 的 cryptography、OpenSSL、BoringSSL。自己造的轮子大多是窟窿。
警告:即便你理解了这三种工具的原理,也不要在生产环境里“拼凑”自己的协议。TLS 1.3 已经帮你把坑都踩平了,直接用标准实现最安全。