TLS、HTTPS、WebSocket wss:// 全面解析

6 阅读3分钟

前言

本文整理了:

  • TLS 握手的每一步
  • 对称加密 vs 非对称加密
  • Netty 如何支持 wss:// 与浏览器加密通信
  • 客户端的加密是谁做的
  • 业务数据加密的时机

一、TLS 是什么?它和 HTTPS、wss:// 的关系

  • TLS:负责加密
  • HTTPS = HTTP + TLS
  • wss:// = WebSocket + TLS

TLS 是一个通用的加密层,不属于 HTTP,也不属于 WebSocket。

浏览器 →(TLS 加密)→ 服务器


二、TLS 握手的完整流程

下面是现代 TLS 1.2 流程(含 RSA/ECDHE)

1. Client

浏览器或客户端发送:

  • TLS 版本
  • 随机数 random1
  • 支持的加密算法列表
  • SNI(域名)

2. Server

服务器返回:

  • TLS 版本
  • 随机数 random2
  • 选择的加密算法(如 TLS_ECDHE_RSA_AES_128_GCM_SHA256)
  • 服务器证书(含公钥)

3. 验证证书(由浏览器做或客户端)

浏览器检查:

  • 是否被 CA 签名
  • 域名是否匹配
  • 是否过期

失败则显示 HTTPS 红色警告。

4. 密钥交换

根据加密算法不同:

  • RSA:客户端用服务器公钥加密 pre_master_key
  • ECDHE:双方交换椭圆曲线公钥,计算共享密钥

5. 生成对称密钥(Session Key)

双方使用:

random1 + random2 + pre_master_key

生成最终用于 数据加密 的对称密钥。

6. Change Cipher Spec

双方通知:“我接下来用 Session Key 加密了”。

7. Finished(第一个被加密的包)

握手完成。

此后:

所有业务数据全部使用对称加密


三、对称加密 vs 非对称加密

非对称加密(RSA/ECDSA/ECDHE)

特点:

  • 公钥加密,私钥解密
  • 只用于 握手阶段(交换对称密钥)

对称加密(AES)

特点:

  • 加解密速度快
  • 用在 业务数据传输阶段

TLS 的黄金组合:

握手用非对称,传输用对称。


四、Netty 如何支持 wss://

Netty 的 wss:// 底层就是:

TCP → TLS → WebSocket

实现步骤:

1. 创建 SSLContext(加载证书)

SslContext sslContext = SslContextBuilder.forServer(certChainFile, privateKeyFile).build();

2. 在 pipeline 前面加一个 SslHandler

pipeline.addLast(sslContext.newHandler(ch.alloc()));
pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));

注意:

  • WebSocket 握手是在明文 HTTP 中进行
  • 但当你使用 wss:// 时 HTTP 部分也是被 TLS 加密的

浏览器连接:

wss://example.com/ws

即可自动通过 TLS 进行加密通信。


五、客户端的加密工作是谁做的?

1. 浏览器中的 TLS 由谁做?

由浏览器内部的 TLS 库完成:

  • Chrome:BoringSSL
  • Firefox:NSS
  • Safari:苹果系统 TLS

程序员完全无法干预加密流程。

2. 应用层(JS)看到的永远是明文

例如:

ws.send("hello");

发送的是明文字符串。

真正加密是在:

  • 浏览器 TLS 层
  • 系统 Socket 层

你的 JS 根本接触不到加密细节。


六、业务数据加密的执行时机

TLS 握手完成后,后续所有应用数据加密由 TLS 记录层 自动完成。

1. 业务发送数据的加密流程

当:

ws.send("hello");

时,流程如下:

  1. JS 生成明文 "hello"
  2. 浏览器将它交给 TLS 层
  3. TLS 使用协商好的对称密钥 AES 自动加密
  4. 加密后的二进制数据才写入 TCP

业务层完全无法参与。


2. 服务端收到数据的解密流程

Netty 服务器收到 TLS 加密数据包:

  1. SslHandler 自动执行解密
  2. 解密后的 WebSocket 帧进入 pipeline
  3. 业务 Handler 看到的永远是明文

示例:

channelRead(ctx, msg)  // msg 已经是明文

3. TLS 与 WebSocket 的关系

WebSocket 不负责加密。

流程如下:

WebSocket 明文帧
     ↓
TLS 自动加密
     ↓
TCP 发送

因此:

业务数据的加密解密时机在 TLS 层,而不是在 WebSocket 层,更不是在业务代码中。


七、总结

  • TLS 是所有 HTTPS/wss:// 加密的核心
  • 握手阶段用 RSA/ECDHE 非对称加密换取对称密钥
  • 业务数据阶段全部使用对称加密(AES/ChaCha20)
  • 浏览器负责加密,程序员完全不用管
  • Netty 通过 SslHandler 实现 wss://
  • 业务代码看到的永远是明文,TLS 自动负责加密/解密