密码学基础回顾:对称加密与非对称加密、哈希函数、数字签名、随机数生成

说实话,很多人在学 TLS 的时候,一上来就被各种握手流程搞懵了。我当年也是这样。后来我发现,真正卡住你的不是协议本身,而是背后的密码学基础。这一章,我们就把这些基础概念彻底捋清楚。

你想想看,TLS 本质上就是在做三件事:身份认证、数据加密、完整性校验。这三件事,分别对应着非对称加密、对称加密和哈希函数。嗯,就是这么简单。

核心认知:TLS 不是发明了新的密码学算法,而是把现有的密码学工具组合成了一个安全的通信协议。理解每个工具的特性,你就能看懂 TLS 为什么这样设计。

密码学基础与 TLS 对应关系 身份认证 你是谁? 数据加密 别人看不懂 完整性校验 有没有被改过? 非对称加密 RSA / ECC 对称加密 AES / ChaCha20 哈希函数 SHA-256 / SHA-384 数字签名 证书验证 会话密钥 数据传输加密 消息认证码 HMAC / AEAD TLS 混合使用对称和非对称加密:用非对称加密安全传递对称密钥,再用对称加密高效传输数据

对称加密:又快又简单,但有个大问题

对称加密,说白了就是加密和解密用同一个密钥。就像你家里的大门,用一把钥匙锁上,也用同一把钥匙打开。

常见的对称加密算法有:

  • AES(Advanced Encryption Standard)—— 目前最主流的对称加密算法,TLS 1.3 里还在大量使用
  • ChaCha20 —— 谷歌力推的流加密算法,在移动设备上性能更好
  • 3DES —— 老古董了,TLS 1.3 已经彻底移除

对称加密最大的优势是快。我在项目中做过压测,AES-256-GCM 在普通服务器上每秒能加密好几 GB 的数据。但它的致命问题是——密钥分发。你想想看,如果通信双方事先没有见过面,怎么安全地把这把钥匙交给对方?

我的经验:曾经有个项目,团队直接用硬编码的 AES 密钥做客户端和服务器通信。上线第一天就被安全团队叫停了。密钥一旦泄露,所有历史数据都能被解密。对称加密的密钥管理,永远是第一道坎。

非对称加密:解决密钥分发难题

非对称加密的思路很巧妙。每个通信方都有一对密钥:公钥和私钥。公钥可以公开给任何人,私钥只有自己知道。

它的核心特性是:

  • 用公钥加密的数据,只能用对应的私钥解密
  • 用私钥加密的数据,只能用对应的公钥解密(这就是数字签名的基础)

常见的非对称加密算法:

算法 密钥长度 安全强度 TLS 中使用情况
RSA 2048 / 4096 位 高 传统握手,TLS 1.3 中已不是必须
ECDHE 256 / 384 位 高(同等安全下密钥更短) TLS 1.3 默认密钥交换
Ed25519 256 位 极高 新兴方案,性能极佳

非对称加密的缺点是慢。RSA 2048 位签名比 AES-256 慢好几个数量级。所以 TLS 不会用它来加密实际数据,而是用它来安全地协商出一个临时对称密钥。

避坑指南:我曾经见过一个项目,直接用 RSA 公钥加密每一笔交易数据。结果服务器 CPU 直接被打满,响应时间从 10ms 飙升到 3 秒。记住:非对称加密只适合加密小数据,比如密钥、哈希值。大数据加密,永远交给对称加密。

哈希函数:数据的指纹

哈希函数能把任意长度的数据,压缩成一个固定长度的摘要。而且这个操作是单向的——从摘要反推原始数据,理论上不可能。

好的哈希函数需要满足三个特性:

  1. 抗碰撞性:很难找到两个不同的输入,产生相同的输出
  2. 单向性:从输出无法反推输入
  3. 雪崩效应:输入改一个比特,输出完全不一样

TLS 中常用的哈希函数:

  • SHA-256 —— TLS 1.3 的默认哈希函数,输出 256 位摘要
  • SHA-384 —— 用于更高安全等级的场景
  • SHA-1 —— 已经不安全了,TLS 1.3 已移除
  • MD5 —— 彻底废弃,不要在任何新项目中使用

关键点:哈希函数不是加密。加密是可逆的,哈希是不可逆的。很多人把这两个概念搞混,面试时经常被问到。

数字签名:证明这东西是你发的

数字签名 = 哈希函数 + 非对称加密。流程是这样的:

  1. 发送方对消息做哈希,得到摘要
  2. 发送方用自己的私钥加密这个摘要,生成签名
  3. 接收方用发送方的公钥解密签名,得到摘要 A
  4. 接收方自己对消息做哈希,得到摘要 B
  5. 如果 A == B,说明消息确实是发送方发的,且没有被篡改

你想想看,这里解决了两个问题:

  • 身份认证:只有持有私钥的人才能生成有效的签名
  • 完整性:消息一旦被改,哈希值就对不上了

在 TLS 中,数字签名主要用于证书验证。CA 机构用它的私钥给你的证书签名,浏览器用 CA 的公钥验证这个签名。这就是整个 HTTPS 信任链的根基。

我的习惯:在调试 TLS 连接问题时,我经常先用 OpenSSL 手动验证证书签名。命令很简单:openssl verify -CAfile ca.pem server.crt。如果这一步都过不了,握手肯定失败。

随机数生成:安全的基础

这个知识点经常被忽略,但我觉得它特别重要。TLS 的整个安全性,都建立在高质量的随机数之上。

为什么?

  • 密钥交换时需要随机数来生成临时密钥
  • 对称加密的 IV(初始化向量)需要随机数
  • TLS 握手过程中的随机数用于防止重放攻击

随机数生成器分两种:

类型 特点 示例 能否用于密码学
伪随机数生成器(PRNG) 基于算法,可预测(如果知道种子) C 语言的 rand() ❌ 不能
密码学安全伪随机数生成器(CSPRNG) 基于熵源,不可预测 /dev/urandom, getrandom() ✅ 可以

我曾经踩过的坑:有个嵌入式项目,设备没有硬件随机数生成器,团队就用 rand() 来生成 TLS 握手的随机数。结果呢?每次重启设备,生成的随机数序列都一样。攻击者只要抓一次包,就能预测后续所有会话的密钥。后来我们换成了从 ADC 噪声中提取熵源,才解决问题。

在 Linux 系统上,我建议你始终使用 getrandom() 系统调用,或者从 /dev/urandom 读取。不要用 /dev/random,它会在熵池不足时阻塞,导致程序卡住。

把这些串起来:TLS 是怎么用它们的?

现在你知道了每个工具的作用,我们来看看 TLS 是怎么把它们组合起来的:

  1. 握手阶段:客户端和服务器交换随机数,协商密码套件
  2. 身份认证:服务器发送证书(包含公钥),客户端验证 CA 的数字签名
  3. 密钥交换:使用 ECDHE 等非对称算法,安全地协商出临时对称密钥
  4. 数据加密:用协商好的对称密钥(如 AES-GCM)加密实际传输的数据
  5. 完整性校验:AEAD 模式同时提供加密和完整性校验,一步到位

你看,每个密码学工具都用在了最合适的地方。非对称加密负责安全的密钥交换,对称加密负责高效的数据加密,哈希函数保证数据完整性,随机数确保每次会话都是独一无二的。

总结一下:学 TLS 不需要你成为密码学专家,但你必须理解这些基础工具的特性和局限性。知道什么场景该用什么工具,什么场景绝对不能混用。后面的章节,我们会一步步把这些知识应用到实际的 TLS 协议分析中。