为什么需要 TLS

HTTP 协议最初设计为明文传输协议,所有通信内容都以纯文本形式在网络中传输。这种设计在互联网早期是合理的,但随着网络应用的普及和敏感数据的增多,明文传输带来了严重的安全风险。

窃听风险

在明文传输模式下,任何能够访问网络链路的攻击者都可以轻易读取通信内容。这包括:

  • 同一局域网内的其他用户
  • 网络服务提供商(ISP)
  • 恶意的路由器或交换机
  • 公共 Wi-Fi 网络的运营者

攻击者可以使用诸如 Wireshark、tcpdump 等网络抓包工具捕获数据包,直接查看其中的内容。这意味着用户名、密码、信用卡号、私密消息等敏感信息都会暴露在攻击者面前。

篡改风险

明文传输不仅允许攻击者读取内容,还允许他们修改传输的数据。攻击者可以在数据包经过的任何位置插入、删除或修改内容,而接收方难以察觉。例如:

  • 将银行转账金额从 100 元改为 10000 元
  • 修改电子邮件的内容
  • 在网页中插入恶意脚本
  • 替换下载的软件包

冒充风险

由于缺乏身份验证机制,攻击者可以冒充合法的服务器与客户端通信。客户端无法确认与之通信的服务器是否真实可信。这使得钓鱼攻击成为可能:攻击者搭建一个与真实银行网站外观相似的假冒网站,诱骗用户输入敏感信息。

TLS(Transport Layer Security,传输层安全协议)正是为了解决这些问题而设计的。它通过加密通信内容防止窃听,通过消息认证码(MAC)防止篡改,通过数字证书验证服务器身份防止冒充。

密码学基础

理解 TLS 需要掌握一些基础的密码学概念。TLS 综合运用了多种密码学技术来实现安全通信。

对称加密

对称加密使用相同的密钥进行加密和解密。常见的对称加密算法包括 AES(Advanced Encryption Standard)、DES、3DES 等。

AES 是目前最广泛使用的对称加密算法,支持 128 位、192 位和 256 位密钥长度。AES 的优点是加密速度快,适合加密大量数据。但对称加密面临密钥分发问题:通信双方必须事先共享密钥,而如何在公开的网络环境中安全地共享密钥是一个挑战。

非对称加密

非对称加密使用一对密钥:公钥和私钥。公钥可以公开分发,私钥必须保密。用公钥加密的数据只能用私钥解密,用私钥签名的数据可以用公钥验证。

常见的非对称加密算法包括 RSA 和 ECC(Elliptic Curve Cryptography)。RSA 基于大整数分解的数学难题,ECC 基于椭圆曲线离散对数问题。相比 RSA,ECC 可以用更短的密钥实现同等的安全性,计算效率更高。

非对称加密解决了密钥分发问题,但计算成本远高于对称加密,不适合加密大量数据。因此 TLS 使用非对称加密来协商对称密钥,然后使用对称密钥加密实际通信数据。

哈希函数

哈希函数将任意长度的输入数据映射为固定长度的输出值(哈希值或摘要)。常见的哈希算法包括 SHA-256、SHA-1、MD5 等。SHA-256 生成 256 位的哈希值,是当前推荐的哈希算法。

哈希函数具有以下特性:

  • 单向性:从哈希值无法推导出原始数据
  • 抗碰撞性:很难找到两个不同的输入产生相同的哈希值
  • 雪崩效应:输入的微小变化会导致哈希值的巨大变化

哈希函数用于验证数据完整性,确保数据在传输过程中未被篡改。

数字签名

数字签名结合了非对称加密和哈希函数,用于验证消息的真实性和完整性。签名过程如下:

  1. 发送方对消息计算哈希值
  2. 用私钥对哈希值加密,生成数字签名
  3. 将消息和数字签名一起发送

验证过程如下:

  1. 接收方用发送方的公钥解密数字签名,得到哈希值
  2. 接收方对接收到的消息重新计算哈希值
  3. 比较两个哈希值,如果相同则验证通过

数字签名确保消息确实来自声称的发送方(因为只有发送方持有私钥),并且内容未被篡改(因为任何修改都会导致哈希值不匹配)。

数字证书

数字证书(X.509 证书)是用于验证公钥所有权的数字文档。证书由受信任的第三方机构——证书颁发机构(Certificate Authority,CA)签发。

证书包含以下主要信息:

  • 证书持有者的名称和公钥
  • 证书颁发机构(CA)的名称
  • 证书有效期
  • 证书序列号
  • CA 对证书的数字签名

证书的目的是将公钥与实体身份绑定起来,确保你使用的公钥确实属于声称的实体,而非攻击者。

证书链

在实际应用中,CA 通常采用层次结构。根 CA 签发中间 CA 的证书,中间 CA 再签发终端实体(如网站服务器)的证书。这就形成了证书链。

验证证书时,需要逐级验证证书链:

  1. 验证服务器证书是否由中间 CA 签发
  2. 验证中间 CA 证书是否由根 CA 签发
  3. 验证根 CA 证书是否受信任(通常预置在操作系统或浏览器中)

如果证书链中的任何一环验证失败,则整个证书链无效。

证书颁发机构(CA)

CA 是受信任的第三方机构,负责签发和管理数字证书。CA 的核心职责包括:

  • 验证证书申请者的身份
  • 签发数字证书
  • 维护证书吊销列表(CRL)
  • 提供在线证书状态协议(OCSP)服务

常见的商业 CA 包括 DigiCert、Sectigo、GlobalSign 等。此外,Let’s Encrypt 提供免费的自动化证书服务。

TLS 1.2 握手过程

TLS 握手是客户端和服务器建立安全通信通道的过程。TLS 1.2 的完整握手过程通常需要 2-RTT(往返时间)。以下是详细的握手步骤:

1. ClientHello

客户端发起握手,发送 ClientHello 消息,包含以下内容:

  • 支持的 TLS 版本(如 TLS 1.2)
  • 支持的密码套件列表(如 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
  • 支持的压缩方法
  • 随机数(Client Random,32 字节)
  • 扩展字段(如 Server Name Indication、支持的椭圆曲线等)

密码套件指定了密钥交换算法、认证算法、对称加密算法和 MAC 算法的组合。

2. ServerHello

服务器响应 ServerHello 消息,包含以下内容:

  • 选定的 TLS 版本
  • 选定的密码套件
  • 选定的压缩方法
  • 随机数(Server Random,32 字节)
  • 会话 ID(可选,用于会话恢复)

服务器从客户端提供的选项中选择双方都支持的最优配置。

3. Certificate

服务器发送数字证书链。证书链从服务器证书开始,依次向上直到根证书。客户端使用这些证书验证服务器的身份。

如果使用匿名密钥交换(不推荐),则不发送此消息。

4. ServerKeyExchange

如果选定的密码套件需要(如使用 DHE 或 ECDHE 密钥交换),服务器发送此消息,包含:

  • 密钥交换参数(如椭圆曲线参数、临时公钥)
  • 对这些参数的签名

签名使用服务器的私钥,客户端可以用证书中的公钥验证签名,确保参数确实来自服务器。

对于 RSA 密钥交换,不需要此消息。

5. ServerHelloDone

服务器发送 ServerHelloDone 消息,表明服务器端的消息发送完毕,等待客户端响应。

6. ClientKeyExchange

客户端发送 ClientKeyExchange 消息,完成密钥交换。

  • 对于 RSA 密钥交换:客户端生成预主密钥(Pre-Master Secret,48 字节),用服务器的公钥加密后发送
  • 对于 ECDHE 密钥交换:客户端生成临时密钥对,发送自己的临时公钥

7. ChangeCipherSpec

客户端发送 ChangeCipherSpec 消息,指示后续消息将使用协商好的加密参数和密钥进行保护。

8. Finished

客户端发送 Finished 消息,验证握手过程是否成功。此消息包含:

  • 对之前所有握手消息的哈希值
  • 使用协商好的密钥加密

服务器解密并验证此消息,确认握手未被篡改。

9. 服务器端的 ChangeCipherSpec 和 Finished

服务器同样发送 ChangeCipherSpec 和 Finished 消息,客户端验证服务器的 Finished 消息。

密钥生成

握手完成后,客户端和服务器各自计算主密钥(Master Secret)和会话密钥:

  1. Master Secret = PRF(Pre-Master Secret, “master secret”, Client Random + Server Random)
  2. 会话密钥 = PRF(Master Secret, “key expansion”, Client Random + Server Random)

会话密钥包括:

  • 客户端写入密钥(加密客户端发送的数据)
  • 服务器写入密钥(加密服务器发送的数据)
  • 客户端写入 MAC 密钥
  • 服务器写入 MAC 密钥

此后,所有应用层数据都使用这些会话密钥加密传输。

密钥交换算法

密钥交换算法是 TLS 握手的核心,决定了客户端和服务器如何协商共享密钥。

RSA 密钥交换

RSA 密钥交换是最传统的密钥交换方式:

  1. 客户端生成随机的预主密钥(48 字节)
  2. 客户端用服务器的公钥(从证书中获取)加密预主密钥
  3. 客户端将加密后的预主密钥发送给服务器
  4. 服务器用私钥解密,获得预主密钥
  5. 双方使用预主密钥和两个随机数计算会话密钥

RSA 密钥交换的缺点是缺乏前向安全性(Perfect Forward Secrecy,PFS)。如果服务器的私钥在将来泄露,攻击者可以解密所有历史通信,因为预主密钥是用服务器的公钥加密的,而攻击者可以获取私钥解密历史通信。

ECDHE 密钥交换

ECDHE(Elliptic Curve Diffie-Hellman Ephemeral)密钥交换提供前向安全性:

  1. 服务器生成临时密钥对(Ephemeral key pair),发送临时公钥
  2. 客户端生成临时密钥对,发送临时公钥
  3. 双方使用对方的临时公钥和自己的临时私钥通过椭圆曲线 Diffie-Hellman 算法计算共享密钥
  4. 共享密钥用于生成会话密钥
  5. 临时密钥对在会话结束后销毁

由于临时密钥对是临时的,即使服务器的长期私钥泄露,攻击者也无法解密历史通信,因为历史通信使用的是已经销毁的临时密钥协商的密钥。

ECDHE 相比传统的 DHE(基于有限域的 Diffie-Hellman)具有以下优势:

  • 更短的密钥长度实现同等安全性
  • 更快的计算速度
  • 更小的消息尺寸

因此,ECDHE 是当前推荐的密钥交换算法。

TLS 1.3 的改进

TLS 1.3(RFC 8446)于 2018 年发布,相比 TLS 1.2 有重大改进,显著提升了安全性和性能。

握手延迟优化

TLS 1.3 将握手延迟从 2-RTT 减少到 1-RTT:

  • 移除了 ServerKeyExchange、ServerHelloDone、ClientKeyExchange、ChangeCipherSpec 等消息
  • 将密钥交换参数合并到 ServerHello 中
  • 服务器在发送 ServerHello 的同时就可以发送加密的应用数据

对于建立新连接,TLS 1.3 只需要 1-RTT 即可完成握手并开始传输数据。

0-RTT 恢复

TLS 1.3 支持 0-RTT 会话恢复,允许客户端在第一次往返中就发送应用数据:

  1. 客户端使用之前会话的会话票据(Session Ticket)或预共享密钥(PSK)
  2. 客户端在 ClientHello 中携带这些信息以及应用数据
  3. 服务器验证后立即处理应用数据

0-RTT 的代价是缺乏前向安全性,因此只适用于非敏感数据。

移除不安全的密码套件

TLS 1.3 移除了所有不安全或过时的密码套件:

  • 移除静态 RSA 密钥交换(无前向安全性)
  • 移除 RC4、DES、3DES 等弱加密算法
  • 移除 SHA-1、MD5 等弱哈希算法
  • 移除 CBC 模式(易受攻击)
  • 移除非 AEAD 密码套件(必须使用认证加密)

TLS 1.3 只保留 AEAD(Authenticated Encryption with Associated Data)密码套件,如 AES-128-GCM、AES-256-GCM、ChaCha20-Poly1305。

加密更多握手内容

TLS 1.3 加密了更多的握手消息(包括 Server Certificate、Certificate Verify 等),防止攻击者获取握手细节。这增强了隐私保护,使得攻击者难以通过分析握手消息推断通信内容。

简化的状态机

TLS 1.3 简化了状态机,移除了 ChangeCipherSpec 协议,减少了实现复杂度和潜在的漏洞。

证书验证过程

证书验证是确保通信安全的关键环节,客户端必须严格验证服务器证书。

证书链验证

证书链验证确保每个证书都由上级 CA 签发:

  1. 检查服务器证书的有效期(开始时间、结束时间)
  2. 检查服务器证书的用途(是否包含 serverAuth 扩展)
  3. 验证服务器证书是否由中间 CA 签发
  4. 验证中间 CA 证书是否由根 CA 签发
  5. 检查根 CA 证书是否在受信任的根证书列表中
  6. 检查证书的签名是否有效
  7. 检查证书是否被吊销

证书吊销检查

证书可能在有效期内被吊销,原因包括私钥泄露、证书信息错误等。吊销检查有两种方式:

CRL(Certificate Revocation List)

CA 定期发布证书吊销列表,包含所有被吊销证书的序列号。客户端下载 CRL 并查询证书是否在列表中。

缺点是 CRL 文件可能很大,下载和查询效率低。

OCSP(Online Certificate Status Protocol)

OCSP 允许客户端实时查询证书状态。客户端向 OCSP 服务器发送证书序列号,服务器返回证书状态(有效、吊销、未知)。

优点是响应快速,但 OCSP 服务器可能成为性能瓶颈。

OCSP Stapling

OCSP Stapling 是 OCSP 的优化方案。服务器定期向 OCSP 服务器查询证书状态,获得带签名的响应,并在 TLS 握手时将响应发送给客户端。

优点是减轻 OCSP 服务器负载,提高验证效率。

证书固定(Certificate Pinning)

证书固定是一种额外的安全措施,客户端预先保存服务器的证书或公钥哈希值,在连接时验证证书是否匹配。

固定方式包括:

  • 固定服务器证书的公钥哈希(HPKP,HTTP Public Key Pinning,已废弃)
  • 固定证书链中的某个证书
  • 固定 CA 的证书

证书固定可以防止 CA 被攻击或签发虚假证书时的中间人攻击,但配置错误可能导致服务不可用。HPKP 已被废弃,现在推荐使用 Expect-CT 头或其他机制。

常见攻击与防御

尽管 TLS 设计为安全协议,但历史上仍发现了一些漏洞和攻击方式。

中间人攻击(MITM)

中间人攻击者拦截并可能修改客户端和服务器之间的通信。

防御措施:

  • 严格验证服务器证书
  • 使用 HSTS(HTTP Strict Transport Security)强制使用 HTTPS
  • 检查证书的有效期、用途和吊销状态
  • 使用证书固定(需谨慎)

降级攻击

攻击者迫使客户端和服务器使用不安全的协议版本或密码套件。例如,攻击者拦截 ClientHello,删除高版本的 TLS 支持,迫使双方使用 TLS 1.0 或 SSL 3.0。

防御措施:

  • 使用 TLS Fallback SCSV(Signaling Cipher Suite Value)
  • 服务器拒绝连接到不安全的协议版本
  • TLS 1.3 在握手消息中加密协商的参数,防止降级

BEAST 攻击

BEAST(Browser Exploit Against SSL/TLS)攻击利用 CBC 模式下的加密漏洞,可以解密部分内容。

影响范围:TLS 1.0 和 SSL 3.0 的 CBC 模式密码套件。

防御措施:

  • 升级到 TLS 1.1 或更高版本
  • 使用 RC4(不推荐,RC4 本身有漏洞)
  • 使用 1/n-1 分块记录技术

POODLE 攻击

POODLE(Padding Oracle On Downgraded Legacy Encryption)攻击利用 SSL 3.0 的 CBC 模式填充漏洞。

防御措施:

  • 禁用 SSL 3.0
  • 使用 TLS 1.0 或更高版本
  • TLS 1.3 完全移除了 CBC 模式

Heartbleed 漏洞

Heartbleed 是 OpenSSL 的实现漏洞,攻击者可以读取服务器内存中的敏感数据(如私钥)。

影响范围:使用 OpenSSL 1.0.1 到 1.0.1f 的版本。

防御措施:

  • 升级 OpenSSL 到修复版本
  • 吊销并重新签发所有证书
  • 更换所有密钥

其他攻击

  • CRIME:利用压缩的侧信道攻击
  • TIME:利用时间差异的侧信道攻击
  • Lucky 13:利用 MAC 验证时间差异的攻击

防御措施包括禁用压缩、使用恒定时间算法等。

实践建议

推荐密码套件

对于 TLS 1.2,推荐以下密码套件(按优先级排序):

1
2
3
4
5
6
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256

对于 TLS 1.3,密码套件简化为:

1
2
3
TLS_AES_256_GCM_SHA384
TLS_AES_128_GCM_SHA256
TLS_CHACHA20_POLY1305_SHA256

禁用不安全的协议和算法

  • 禁用 SSL 2.0、SSL 3.0
  • 禁用 TLS 1.0、TLS 1.1(除非必须兼容旧客户端)
  • 禁用 RC4、DES、3DES
  • 禁用 SHA-1、MD5
  • 禁用静态 RSA 密钥交换
  • 禁用 CBC 模式

配置 HSTS

HSTS(HTTP Strict Transport Security)强制浏览器只通过 HTTPS 连接,防止降级攻击和 SSL Stripping 攻击。

配置示例:

1
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

参数说明:

  • max-age:HSTS 策略的有效期(秒)
  • includeSubDomains:策略应用于所有子域名
  • preload:加入 HSTS Preload 列表(浏览器内置)

启用 OCSP Stapling

OCSP Stapling 提高证书验证效率,减少 OCSP 服务器负载。

Nginx 配置示例:

1
2
3
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /path/to/chain.pem;

Apache 配置示例:

1
2
SSLUseStapling on
SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"

使用现代 TLS 配置

推荐使用 Mozilla SSL Configuration Generator 生成安全的 TLS 配置:

  • Old:兼容性最好,安全性较低
  • Intermediate:平衡兼容性和安全性(推荐)
  • Modern:最高安全性,兼容性较差

定期更新和监控

  • 定期更新服务器软件和 OpenSSL 版本
  • 监控证书有效期,及时续期
  • 使用自动化工具(如 Let’s Encrypt)管理证书
  • 定期进行安全审计和渗透测试

测试 TLS 配置

使用以下工具测试 TLS 配置的安全性:

总结

TLS 是现代互联网安全通信的基石,综合运用了对称加密、非对称加密、哈希函数、数字签名和数字证书等多种密码学技术。理解 TLS 握手过程、密钥交换算法、证书验证机制以及常见攻击方式,对于配置和维护安全的 TLS 服务至关重要。

TLS 1.3 的引入显著提升了安全性和性能,但许多旧系统仍使用 TLS 1.2 或更早版本。在实际应用中,应根据兼容性和安全性需求选择合适的协议版本和密码套件,并定期更新和测试配置。

随着量子计算的发展,后量子密码学(Post-Quantum Cryptography)将成为未来 TLS 的重要研究方向。目前,IETF 正在制定后量子 TLS 标准,以应对量子计算对现有加密算法的威胁。