加密和签名
加密和签名
加密:公钥加密,私钥解密。
签名:私钥签名,公钥验签。
| 特性 | 加密 | 签名 |
|---|---|---|
| 目的 | 保密 | 验证身份、完整性 |
| 结果 | 密文 | 数字签名 |
| 解密者 | 接收者 | 接收者验证签名 |
| 密钥方向 | 公钥加密,私钥解密(非对称) | 私钥签名,公钥验签 |
签发证书
根 CA 证书的私钥一般离线保存,不会直接签发服务器证书。根 CA 只签发中间 CA → 中间 CA 再签发服务器证书。签发服务器证书过程如下:
- 网站生成自己的公私钥对
- 网站通过公钥、域名、公司等信息创建一个 CSR(Certificate Signing Request),将 CSR 发给一个 CA(证书颁发机构,如 Let's Encrypt, DigiCert)。
- CA 验证身份(比如通过 DNS 验证网站域名归属),CA 用它的中间证书的私钥对 CSR 签名,生成服务器证书(.crt 或 .pem 文件),CA 会把服务器证书和中间证书一同返回给网站。
网站收到 CA 签发的证书之后,会在服务器进行配置。服务器配置时,将服务器证书和中间证书合并为一个文件(PEM 多段),这个拼接的文件被称为证书链文件,服务器在 TLS 握手时发送整个链,让客户端一步步向上验证到可信的 Root CA.
ssl_certificate /etc/ssl/fullchain.pem; # 包含 leaf + 中间证书
ssl_certificate_key /etc/ssl/private.key; # 私钥
验证证书
CA 机构颁发证书流程(以 Let’s Encrypt 为例):
ECDSA 用户证书 ← ECDSA 中间证书(E5 或 E6)← ISRG Root X1
客户端收到证书链 [Leaf, Intermediate, (Root optional)] 之后,验证过程如下:
- 验证 Leaf 证书的签名 —— 用 Intermediate 证书的公钥
- 验证 Intermediate 证书的签名 —— 用 Root 证书的公钥
- 检查 Root 是否存在于客户端的受信任根证书列表
- 所有签名验证成功 ⇒ 认证通过
证书链结构在逻辑上是从 Root → Intermediate → Leaf 建立的。CA 们按这个方向颁发证书(签名)。
证书链的验证是从服务器证书(最下级)开始,一步步“往上”验证签名,一直验证到根证书为止。
| 阶段 | 行为 | 顺序 |
|---|---|---|
| CA 机构签发证书 | 根 CA → 中间 CA → 服务器证书 | 从上往下 |
| 浏览器验证证书链 | 服务器证书 → 中间证书 → 根 CA | 从下往上 |
HTTPS 建立连接过程
以 TLS 1.3 协议为例,TLS 握手阶段主要完成以下四件大事:
| 阶段 | 目的 |
|---|---|
| 1. 握手(握手阶段) | 协商协议版本、密码算法,生成随机数等 |
| 2. 身份认证 | 验证服务器证书合法性,防中间人攻击 |
| 3. 密钥协商 | 安全地建立对称密钥,用于加密传输 |
| 4. 加密通信 | 使用协商好的对称密钥进行加密传输 |
📘 使用 TLS 1.3 的全过程(现代浏览器默认使用)
我们以 TLS 1.3 为例(相比 TLS 1.2 简化了很多),详细讲解全过程。
🔐 第 0 步:客户端准备
客户端(浏览器)准备:
- 支持的 TLS 版本(例如 TLS 1.3)
- 支持的密码套件(如
TLS_AES_128_GCM_SHA256) - 支持的密钥交换算法(如
X25519) - 生成一个随机数(
client_random) - 生成一个 ECDHE 公钥(用于密钥交换)
🧾 第 1 步:ClientHello(客户端发起)
客户端向服务器发送 ClientHello,包括:
ClientHello {
version: TLS 1.3,
random: client_random,
cipher_suites: [TLS_AES_128_GCM_SHA256, ...],
key_share: [ECDHE 公钥],
supported_groups: [X25519, secp256r1, ...]
}
🔐 第 2 步:ServerHello(服务器回应)
服务器收到 ClientHello 后:
- 选定双方支持的密码算法(如 TLS_AES_128_GCM_SHA256)
- 生成自己的随机数(
server_random) - 生成自己的 ECDHE 公钥
- 选一个自己的证书(通常是服务器证书,含 RSA/ECDSA 公钥)
- 用证书对应私钥签名整个握手内容,证明身份
返回如下:
ServerHello {
random: server_random,
key_share: [ECDHE 公钥],
certificate: 服务器证书链(leaf + intermediate)
CertificateVerify: 用服务器私钥签名握手数据
Finished: 对全部握手数据生成 MAC 校验
}
🛂 第 3 步:客户端验证服务器身份
客户端收到服务器证书链后:
-
验证证书链:
- 使用本地的根 CA 公钥,逐级验证中间证书 → Leaf 证书
-
验证签名:
- 使用 Leaf 证书的公钥验证
CertificateVerify签名(确认服务器确实拥有私钥)
- 使用 Leaf 证书的公钥验证
验证通过 ⇒ 确认服务器身份可信
🔑 第 4 步:共享密钥计算(ECDHE)
客户端与服务器分别用自己的私钥 + 对方的公钥进行 ECDH 运算,这一步输出的 shared_secret 是相同的。:
shared_secret = ECDH(client_private, server_public)
然后使用 HKDF(HMAC-based KDF)进行密钥派生:
handshake_secret = HKDF(shared_secret, client_random, server_random)
application_secret = HKDF(handshake_secret, “finished”, …)
得出:
- 对称加密密钥(如 AES-128-GCM)
- 消息完整性验证密钥(HMAC)
✅ 第 5 步:客户端发送 Finished
客户端也发送一个 Finished 消息,表明:
- 握手过程没被篡改
- 客户端也完成密钥协商
此后双方正式进入应用层加密通信。
🔐 第 6 步:加密传输阶段(HTTP 加密)
此时 HTTP 请求和响应全部使用协商好的对称加密算法进行加密。
加密内容包括:
- HTTP 请求/响应头与正文
- Cookie、表单数据
- TLS 自身的验证消息等
如:
- 浏览器发出
GET /index.html,数据先被 AES 加密 - 服务端返回 HTML 内容,也使用对称密钥加密
整个通信过程为:
[客户端] ⇄ (TLS加密层) ⇄ [服务器]
↑ ↑
HTTP HTTP
📌 补充:TLS 1.3 安全特性
| 特性 | 含义 |
|---|---|
| Forward Secrecy | 前向保密性,历史通信无法因密钥泄漏而解密 |
| 少量 RTT(0-RTT) | 可缓存会话密钥,提升性能 |
| 更强加密 | 默认仅支持 AEAD(如 AES-GCM,ChaCha20) |
| 简化握手 | 无 ServerKeyExchange、无 ChangeCipherSpec |
🧠 总结流程图(TLS 1.3)
ClientHello (ECDHE 公钥 + 支持的套件)
↓
ServerHello (ECDHE 公钥 + 服务器证书链 + 签名)
↓
双方计算 shared_secret(ECDHE)
↓
验证服务器身份(证书 + 签名)
↓
双方生成对称密钥(HKDF 派生)
↓
客户端发送 Finished(握手完成)
↓
双向使用对称加密通信(HTTP over TLS)
🔧 实际抓包工具
你可以用以下工具实际查看 TLS 握手细节:
Wireshark(过滤条件:tcp.port == 443或tls)openssl s_client -connect example.com:443 -tls1_3 -showcertscurl -v --http2 https://example.com
✅ 总结
| 阶段 | 目的 | 安全机制 |
|---|---|---|
| ClientHello | 发起连接,请求协商 | 客户端随机数、支持的算法 |
| ServerHello | 响应连接,返回证书 | 服务器证书、公钥签名、ECDHE 公钥 |
| 验证证书 | 防中间人攻击 | 签名 + 证书链验证 |
| 密钥协商 | 建立对称密钥 | ECDHE + HKDF |
| Finished | 确认握手成功 | HMAC 校验所有握手数据 |
| 加密通信 | 传输数据 | AES-GCM / ChaCha20 |

浙公网安备 33010602011771号