HTTPS加密与证书完全指南(上)

1. 什么是HTTPS

HTTPS = HTTP + TLS(传输层安全协议)

HTTP本身是明文传输,HTTPS通过TLS层对HTTP内容进行加密,保证数据在传输过程中不被窃听和篡改。

加上TLS

HTTPS(加密)

TLS加密

TLS加密

客户端

服务器

HTTP(明文)

明文请求

明文响应

客户端

服务器

形象类比:

  • HTTP = 明信片,邮递员、邻居都能看到内容
  • HTTPS = 把明信片装进保险箱再寄,只有收件人能打开
  • HTTP是"内容",TLS是"包装"。HTTP负责说什么,TLS负责加密

2. TLS握手流程

TLS握手分为两个阶段:非对称加密用于密钥交换/签名验证,对称加密用于后续通信。

形象类比: TLS握手 = 两个人第一次见面要秘密通信

  1. 见面打招呼(TCP握手)
  2. 互相介绍自己支持什么语言(Client/Server Hello)
  3. 出示身份证证明自己是谁(服务器证书)
  4. 协商出一把只有双方知道的会话密钥
  5. 以后都用会话密钥加密通信

重要说明(两种密钥交换方式)

密钥交换有两种方式,区别决定了"前向保密(PFS)"这一安全特性:

RSA 密钥交换 无 PFS — TLS 1.2 起不推荐,TLS 1.3 已移除

服务器 网络 客户端 服务器 网络 客户端 生成 pre-master secret(随机数) 用私钥解密,得到 pre-master 双方用 pre-master 生成相同的对称密钥 pre-master 经过了网络 → 私钥泄露 = 历史流量全暴露 用服务器公钥加密 pre-master 密文在网络上传输一趟

什么是 pre-master secret(预主密钥)?

  • 客户端生成的一个随机数,用来推导出主密钥(master secret),再由主密钥生成实际的会话密钥。
  • 密钥推导链:pre-master secretmaster secretsession keys(加密密钥 + MAC 密钥)
  • RSA 方式下,这个随机数需要"穿过网络"发给服务器,一旦私钥泄露,攻击者就能解密这段密文,拿到 pre-master,进而推算出所有会话密钥。

ECDHE 密钥交换 有 PFS — TLS 1.3 强制使用,现代主流

服务器 网络 客户端 服务器 网络 客户端 生成 DH 私钥 a + 公钥 A 生成 DH 私钥 b + 公钥 B 只传输公钥(公开信息) 用 a + B 本地计算共享密钥 用 b + A 本地计算共享密钥 双方得到相同的共享密钥 共享密钥从未经过网络 → 私钥泄露 ≠ 历史安全 发送公钥 A 发送公钥 B

什么是 DH / ECDHE?

  • DH(Diffie-Hellman,迪菲-赫尔曼)是一种密钥交换算法,核心能力:双方在公开信道上协商出一个共享密钥,窃听者即使看到所有交换数据也算不出来。
  • ECDHE = Elliptic Curve Diffie-Hellman Ephemeral(临时椭圆曲线迪菲-赫尔曼)
    • EC(椭圆曲线):比传统 DH 更快更安全
    • E(临时):每次握手都生成新的临时密钥对,用完即丢,实现前向保密
  • 数学原理(简化版):双方各选一个私密数字 a、b,约定一个公开的底数 g 和模数 p,交换 g^a mod p 和 g^b mod p,各自计算 (ga)b = (gb)a = g^(ab) mod p,得到相同的共享密钥。窃听者只知道 g^a 和 g^b,无法推出 g^(ab)。

2.1 TLS 1.2(RSA 密钥交换,已不推荐)

服务器 客户端 服务器 客户端 TLS握手(非对称加密阶段) 验证证书(CA签名、有效期、域名) 对称加密通信开始 Client Hello(TLS版本、加密套件、随机数random1) Server Hello(选定版本、加密套件、随机数random2) 服务器证书(含公钥) ServerHelloDone ClientKeyExchange(用公钥加密pre-master secret) ChangeCipherSpec Finished(加密的握手消息) ChangeCipherSpec Finished

什么是 ChangeCipherSpec?

  • 一个单字节的信号消息,告诉对方:“从下一条消息开始,我发的所有内容都是加密的。”
  • 双方各发一次,确认"从现在起进入加密通信"。它标志着从明文握手阶段切换到密文传输阶段。

问题: 如果服务器私钥日后泄露,攻击者只要之前录制过流量,就能解密所有历史会话(无前向保密)。

2.2 TLS 1.2(ECDHE)/ TLS 1.3(现代主流,推荐)

服务器 客户端 服务器 客户端 TLS握手(ECDHE 密钥交换,TLS 1.2 / 1.3) 双方各自用 ECDHE 参数计算出共享密钥 验证证书 + 验证 CertificateVerify 签名 对称加密通信开始 Client Hello(加密套件、随机数、ECDHE参数) Server Hello(选定套件、随机数、ECDHE参数) 服务器证书 + CertificateVerify(用私钥对握手签名) Finished Finished

为什么更安全? 共享密钥由双方本地计算生成,从不传输,握手后即丢弃临时参数;即使私钥泄露,历史流量也无法解密(前向保密 PFS)。

3. 非对称加密 vs 对称加密

特性 非对称加密 对称加密
密钥 公钥+私钥(一对) 共享密钥(一个)
速度 慢100-1000倍
用途 密钥交换、签名 数据加密
使用时机 TLS握手阶段 握手后的通信阶段

TLS 的巧妙之处在于:用慢的非对称加密安全地交换密钥,然后切换到快的对称加密传输数据——兼顾安全与性能。

4. 证书是什么

证书(SSL/TLS Certificate)是数字身份证,由受信任的CA(证书颁发机构)签发,包含域名、公钥、CA签名和有效期。

客户端拿到证书后验证:“这个身份证是公安局(CA)发的吗?”——用自己的 CA 证书验证签名,通过就信任。

签发

签发

根CA证书
自签名,离线保存

中间CA证书
在线签发

服务器证书
部署在服务器

包含:域名/IP + 公钥 + CA签名 + 有效期

5. 证书文件详解

以自建CA为例,生成5个文件:

文件 作用 类比
ca.crt CA根证书,放在客户端信任 政府公章
ca.key CA私钥,签发证书用 政府印章本体
server.crt 服务器证书,发给客户端验证 身份证
server.key 服务器私钥,TLS解密用 银行卡密码
server.csr 签名请求,申请证书时的申请表 办证申请表

实际使用:

  • 你只需要把 server.crtserver.key 放到服务器上
  • ca.crt 放到客户端
  • ca.key 存好别泄露,以后要签新证书还得用它

6. 证书生成方式

6.1 自签名证书(内网推荐)

形象类比: 自签名证书 = 公司内部工牌

  • 公共CA = 公安局发的身份证(全社会认可)
  • 自签名CA = 公司HR发的工牌(只在公司内部有效)

内网环境用自签名证书就够了,不需要花钱买公共CA证书

自签名证书生成流程:

1 准备 san.cnf
配置域名 + SAN 扩展

2 生成 CA 私钥 + 根证书
openssl genrsa + req -x509

3 生成服务器私钥 + CSR
openssl genrsa + req

4 CA 签发服务器证书
openssl x509 -req

得到 ca.crt / server.crt / server.key

现代浏览器必须配 SAN(Subject Alternative Name)
Chrome 58+ / Firefox / Safari 等现代浏览器已不再校验 CN 字段,只认证书中的 SAN 扩展。
如果不配置 SAN,浏览器会报 NET::ERR_CERT_COMMON_NAME_INVALID,即使 CN 填对了也没用。
因此下方命令必须带上 v3_ext 配置和 -extfile 参数。

第 1 步:准备配置文件 san.cnf(包含 SAN 和 CA 属性)

# san.cnf —— CA 与服务器证书共用,按需修改 [alt_names]
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no

[req_distinguished_name]
CN = cloud.example.com

[v3_req]
subjectAltName = @alt_names
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth

[alt_names]
DNS.1 = cloud.example.com
DNS.2 = *.internal.example.com
IP.1 = 192.168.1.10

第 2 步:生成 CA 私钥与根证书

# 生成 CA 私钥(推荐 4096 位,CA 是信任根,强度更高)
openssl genrsa -out ca.key 4096

# 生成 CA 根证书(自签名,显式声明 sha256 与 CA:TRUE)
openssl req -new -x509 -days 3650 -sha256 -key ca.key -out ca.crt \
  -subj "/CN=My Private CA" \
  -addext "basicConstraints=critical,CA:TRUE" \
  -addext "keyUsage=critical,keyCertSign,cRLSign"

第 3 步:生成服务器密钥与 CSR

# 生成服务器私钥
openssl genrsa -out server.key 2048

# 生成证书签名请求(使用 san.cnf 注入 SAN 扩展请求)
openssl req -new -key server.key -out server.csr -config san.cnf

第 4 步:用 CA 签发服务器证书(带上 SAN 扩展)

# 用 CA 签发,显式 sha256,并将 san.cnf 中的 v3_req 扩展写入证书
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
  -CAcreateserial -out server.crt -days 825 -sha256 \
  -extfile san.cnf -extensions v3_req

关于 -days 有效期

  • 公共 CA 受 CA/B Forum 规则限制,单域名证书最长有效期现为 397 天(约 13 个月)。
  • 自建 CA 不受此限制,但建议设置为 825 天(浏览器旧版 DV 证书上限)或更短,配合自动轮换。

验证生成的证书:

# 查看证书详情,确认 SAN 已写入
openssl x509 -in server.crt -text -noout | grep -A 1 "Subject Alternative Name"

6.2 免费公共CA(Let’s Encrypt)

形象类比: Let’s Encrypt = 免费的自动办证机

  • 传统CA(如DigiCert)= 去公安局排队办证(收费、审核慢)
  • Let’s Encrypt = 自助办证机(免费、秒级签发、自动续期)
  • 适合个人网站、开发测试环境
Let's Encrypt CA certbot 用户 Let's Encrypt CA certbot 用户 完成挑战(放文件/加TXT记录) certbot certonly -d example.com 申请证书(CSR) 挑战验证(HTTP-01 / DNS-01) 验证通过 签发证书 证书保存到 /etc/letsencrypt/

6.3 Wildcard 通配符证书与 SAN 多域名证书

一台服务器往往要同时服务多个域名,常见有三种处理方式:

方式 示例 覆盖范围 适用场景
单域名证书 cloud.example.com 仅一个域名 单一服务
Wildcard 通配符 *.example.com 同级所有子域名 子域名数量多、频繁变动
SAN 多域名(UCC) a.com + b.com + x.a.com 任意多个指定域名 多个不相关域名共用一张证

三种证书覆盖范围对比:

SAN 多域名 a.com + b.com + x.a.com

覆盖

覆盖

覆盖

不覆盖

a.com

b.com

x.a.com

c.com

Wildcard 通配符 *.example.com

覆盖

覆盖

不覆盖

不覆盖

a.example.com

b.example.com

example.com 裸域

a.b.example.com 多级

单域名证书

覆盖

不覆盖

不覆盖

cloud.example.com

api.example.com

example.com

形象类比:

  • Wildcard = 一张"全家福工牌":张三家所有人(*.zhang.com)都能用,但只认这一级,孙子辈(a.b.zhang.com)不认
  • SAN = 一张"联名工牌":正面是 A 公司,背面还能印 B 公司、C 公司(一张证书里写多个域名)

注意 Wildcard 的限制:

  • *.example.com 只匹配 a.example.comb.example.com不匹配 example.com(裸域)和 a.b.example.com(多级)
  • 若裸域也要覆盖,需在 SAN 里同时加上 example.com

Let’s Encrypt 申请通配符证书(必须用 DNS-01 验证):

# 通配符证书需要 DNS TXT 记录验证,不能用 HTTP-01
certbot certonly --manual --preferred-challenges dns \
  -d "*.example.com" -d example.com

6.4 证书有效期与自动续期

2020 年后,证书有效期大幅缩短

  • CA/B Forum 已将 DV 单域名证书最长有效期从原本的数年压缩到 397 天
  • Let’s Encrypt 证书有效期仅 90 天
  • 苹果于 2025 年宣布将进一步推动缩短至 47 天,未来证书轮换必须自动化

为什么缩短? 降低"证书+私钥泄露后可被长期利用"的窗口期,推动自动化运维。

Let’s Encrypt 自动续期(certbot 自带):

# 测试续期流程(不真正续期,推荐上线前先跑)
certbot renew --dry-run

# 续期命令可加入 cron / systemd timer,certbot 安装时通常会自动配置
certbot renew --quiet

# 续期后重启依赖证书的服务(在 /etc/letsencrypt/renewal-hooks/deploy/ 放脚本)
#!/bin/bash
systemctl reload nginx
systemctl reload dovecot

自建 CA 场景的轮换建议:

  • 把生成命令写成脚本,证书文件用版本号或日期命名(如 server-202606.csr
  • 建立到期监控(Prometheus blackbox_exporter、Nagios check_cert 等都可检查证书剩余天数)
  • 在到期前 30 天自动触发重新签发与分发

7. 客户端如何获取CA证书

形象类比: 安装CA证书 = 小区门禁录入

你家门口小区的门禁系统,物业要先把你家人的信息录进去,你刷脸才能进。
ca.crt就是"录入信息"这一步。

公网场景:

预装

操作系统/浏览器

公共CA证书

自动验证,无需手动安装

内网场景:

ca.crt

自建CA

手动安装到客户端

安装到系统信任存储

连接时自动验证

7.1 安装方式

平台 安装位置
Windows 受信任的根证书颁发机构
macOS 钥匙串 → 系统 → 添加到信任
Android 安全 → 加密与凭据 → 安装证书
iOS 描述文件 → 安装 → 设置信任

8. SSL vs TLS

形象类比: SSL vs TLS = "拨号上网"这个词

"拨号上网"这个说法已经不用了,但"上网"这个词还留着。
SSL已经废弃,但"SSL证书"这个叫法深入人心,实际用的都是TLS。

废弃 SSL 2.0 1995年 已废弃 SSL 3.0 1996年 已废弃 TLS 1.0 1999年 已废弃 TLS 1.1 2006年 已废弃 现行 TLS 1.2 2008年 兼容主流 TLS 1.3 2018年 推荐主流 SSL/TLS 协议演进
版本 状态 特点
SSL 2.0/3.0 废弃 有严重漏洞(POODLE 等)
TLS 1.0/1.1 废弃 2020 年起被主流浏览器/CA 全面停用
TLS 1.2 兼容主流 仍在广泛使用,作为老客户端兼容方案
TLS 1.3 推荐主流 更快(1-RTT)、更安全(强制 PFS),现已占全网 HTTPS 流量 70% 以上

9. 企业内网TLS部署场景

典型架构采用反向代理+内网转发:

形象类比: 反向代理架构 = 公司前台

  • 外部用户 = 访客
  • Nginx 反向代理 = 前台(接待访客、验证身份、转发工单)
  • 后端微服务 = 各部门(只处理前台转来的业务)

Nginx就是前台的分拣规则:“这个请求是给订单服务的,转过去”

TLS

内网转发

加密范围

TLS在Nginx终止

证书部署在Nginx上

外部用户

Nginx 反向代理

后端微服务

9.1 多个服务共用证书

证书(一张)
├── 域名:api.example.com
├── 公钥 + 私钥
└── 部署在Nginx反向代理上

优点: 实现简单,客户端只需信任一个CA

缺点: 证书泄露影响所有后端服务


[!info] 下一篇
中篇:[[HTTPS-TLS加密与证书完全指南(中)]] — 证书链、证书吊销、CT、HSTS、mTLS、PFS、常见TLS攻击

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐