密码学基础:对称加密、非对称加密、哈希函数与数字签名在TLS中的应用

说实话,很多开发者刚开始接触TLS时,把证书一配、HTTPS一开就完事了。但他们没想过——加密通道到底是怎么建立起来的?握手过程中用了哪些密码学工具?

我之前有个项目,测试环境一切正常,上了生产之后偶尔会出现握手失败。查了三天,最后发现是客户端和服务端的密码套件列表没对齐,一个只支持旧版的SHA-1,另一个已经废弃了它。从那以后,我就养成了一个习惯:先把密码学基础搞透,再去配协议。

为什么TLS需要密码学

网络通信本质是不安全的。中间人可以监听、篡改、重放。TLS要解决四个问题:

  • 机密性:数据只有双方能看懂,中间人看不懂
  • 完整性:数据在传输中没被改过
  • 身份认证:对方确实是声称的那个人
  • 不可否认性:对方不能抵赖自己发过的内容

单独一种密码学技术搞不定所有。所以才有了TLS握手阶段的多步配合。

对称加密:SSL/TLS的加解密引擎

对称加密,说白了就是加密和解密用同一个密钥。速度快,适合批量数据加密。TLS记录层里传输的业务数据,都是用对称加密来保护的。

我见过有人问:“既然非对称加密更安全,为什么不用它加密全部数据?”原因很简单——慢。非对称加密比对称加密慢几百上千倍,用来加密整条视频流根本不现实。

算法密钥长度TLS中常见套件状态
AES128 / 256 bitsTLS_AES_128_GCM_SHA256推荐
ChaCha20256 bitsTLS_CHACHA20_POLY1305_SHA256推荐(移动端常用)
3DES168 bits已废弃不推荐,易受攻击
RC4可变已禁用存在严重漏洞,已废弃
个人习惯:我通常优先选择 AES-256-GCM,如果客户端是低功耗 IoT 设备,会考虑 ChaCha20-Poly1305。前者有硬件加速,后者纯软件性能更好。

非对称加密:密钥交换与身份认证

非对称加密有一对密钥:公钥和私钥。公钥公开,私钥只有自己知道。它解决了对称加密中“密钥怎么安全分发给对方”的问题。

在TLS中,非对称加密主要用于两件事:

  • 密钥交换:握手时协商出临时对称密钥(比如 ECDHE)
  • 身份认证:服务器用私钥签名证书,客户端用公钥验证

以前主流是RSA密钥交换,但RSA不能提供前向安全性(Forward Secrecy)。什么意思?如果私钥泄露了,之前所有的通信记录都能被解密。所以现在推荐用 ECDHE(椭圆曲线 Diffie-Hellman 临时密钥交换)。

前向安全性(Forward Secrecy)
每次握手独立生成临时密钥,即使服务器长期私钥泄露,也无法解密以往的会话数据。ECDHE 是标配。

哈希函数:完整性保护

哈希函数把任意长度的数据映射成固定长度的摘要。特点:不可逆、抗碰撞。在TLS中,哈希函数用来:

  • 计算 Finished 消息的摘要,确保握手过程没被篡改
  • 生成密钥派生所需的伪随机数(PRF)
  • 配合数字签名对证书摘要签名

常用的有 SHA-256、SHA-384。MD5 和 SHA-1 已经不建议使用了。我之前维护过一套老系统,用的 SHA-1 证书链,Chrome 直接弹出“不安全”,用户投诉了一堆。后来全部换成了 SHA-256。

哈希算法摘要长度TLS中使用安全性
SHA-256256 bits最常用高
SHA-384384 bits某些套件高
SHA-1160 bits逐步弃用已出现碰撞攻击
MD5128 bits已禁用完全不可用

数字签名:防抵赖与证书验证

数字签名 = 哈希 + 非对称加密。发送方对消息摘要用私钥加密,接收方用公钥解密并对比摘要。

TLS中,服务器在 Certificate 消息中发送证书,同时用证书私钥对握手上下文签名(CertificateVerify)。客户端用证书里的公钥验证签名,从而确认服务器确实持有对应的私钥。

嗯,这里要注意:数字签名并不加密消息本身,它只保证消息是谁签的、有没有被改过。我遇到过有人误以为签名就是加密,其实不然。

常见坑:我曾经遇到过证书链不完整的问题——服务端只发了终端证书,没发中间 CA 证书。客户端因为本地没有信任中间 CA,验证签名时失败。记得在服务端配置完整证书链。

四者在TLS握手中的配合

讲了这么多,它们到底怎么配合?下面这张图展示了 TLS 1.3 握手的关键步骤:

TLS 1.3 握手中的密码学组件配合 客户端 服务端 ClientHello (密钥交换算法、随机数) ServerHello + Certificate + CertificateVerify (数字签名) 验证签名 + 哈希校验 (非对称+哈希) Finished (哈希+对称加密) (完整性保护) 握手结束后,对称密钥用于加密应用数据(AES-GCM / ChaCha20-Poly1305)

你看,整个过程里:

  • 非对称加密(ECDHE)用来安全交换临时密钥参数
  • 数字签名(RSA 或 ECDSA)用来验证证书合法性
  • 哈希函数(SHA-256)用于计算摘要、密钥派生和 Finished 校验
  • 对称加密(AES-GCM)负责最后的数据加密

少了哪个都不行。我曾经在调试时把哈希函数改成了 MD5 做测试,结果 OpenSSL 直接报错——现在兼容性要求已经不允许这么玩了。

避坑与实践建议

  • 不要混用密码套件:有的算法组合虽然名字上能拼起来,但安全强度不匹配。例如 RSA 密钥交换配合 RC4,都是弱鸡。
  • 优先使用 TLS 1.3:它只支持前向安全的密钥交换,且移除了很多不安全算法。我目前所有的生产环境都切到了TLS 1.3。
  • 检查证书签名算法:证书中签名算法必须是 SHA-256 及以上。SHA-1 的证书在 2025 年基本都被各大浏览器拉黑了。

最后说句实在话:密码学基础不是背公式,而是理解每种工具解决什么问题、有什么限制。你把这个想清楚了,调起TLS SDK来心里就有底。