3. 数字证书与CA
说到TLS,绕不开的就是数字证书。我刚开始接触这玩意儿的时候,也觉得不就是个文件嘛。后来被坑过几次,才明白这里面的门道有多深。
说白了,数字证书就是网络世界里的「身份证」。但它比身份证复杂得多。咱们这一章,就把证书的里里外外扒个干净。
3.1 X.509 证书是什么?
X.509 是一种国际标准,定义了公钥证书的格式。目前主流的是 X.509 v3 版本。几乎所有 HTTPS 网站用的都是它。
你打开浏览器,点那个小锁图标,看到的证书信息,就是 X.509 格式。我印象里,有一次排查一个双向认证失败的问题,查了两天,最后发现是证书里的扩展字段写错了。
证书的本质,就是把「公钥」和「身份信息」绑定在一起。谁来担保这种绑定关系呢?证书颁发机构——也就是 CA。
3.2 证书结构详解
一个标准的 X.509 v3 证书,包含以下核心字段。我建议你把这个表格背下来,排查问题的时候会很有用。
| 字段 | 说明 | 我的经验提醒 |
|---|---|---|
| 版本号 | 目前主流是 v3 | v1/v2 已经很少见了,别用 |
| 序列号 | CA 给每个证书的唯一编号 | 吊销证书时用这个字段 |
| 签名算法 | 比如 SHA256-RSA | 别用 SHA1,已经不安全了 |
| 颁发者 | 签发这张证书的 CA 名称 | 必须和上级证书的主体一致 |
| 有效期 | 生效日期和过期日期 | 我见过证书过期导致服务挂了的,惨 |
| 主体 | 证书持有者的身份 | 域名写在 CN 或 SAN 里 |
| 公钥 | 持有者的公钥信息 | RSA 2048 位起步 |
| 扩展 | 关键用途、基本约束等 | 这部分最容易出错 |
最容易被忽视的扩展字段:
- Key Usage: 指定密钥用途,比如数字签名、密钥加密。
- Extended Key Usage: 更精细的用途,比如服务器认证、客户端认证。
- Subject Alternative Name (SAN): 现在域名都写在这里,CN 基本废弃了。
- Basic Constraints: 标记是不是 CA 证书。
你想想看,如果一个服务器证书没加「服务器认证」的 EKU,那浏览器就会报错。我在项目中遇到过这种事,当时所有人都觉得配置没问题,结果就是少了一个扩展。
3.3 证书链
证书链,说白了就是信任的链条。一张证书不是凭空存在的。它是由上一级 CA 签发的,上一级又是由更上一级签发的。最顶上的那个,叫根证书。
我举个例子。你访问 www.example.com。服务器发过来的证书,是由「中间 CA」签发的。中间 CA 的证书,又是由「根 CA」签发的。根 CA 的证书,预装在操作系统或浏览器里。
校验过程是这样的:
- 用根 CA 的公钥,验证中间 CA 证书的签名。
- 用中间 CA 的公钥,验证服务器证书的签名。
- 如果都通过了,就信任服务器证书。
这就是一个典型的信任传递。你不需要信任每个网站,你只需要信任几个根 CA。
避坑指南: 我曾经在配置双向认证时,只发了服务器证书,没发中间证书链。结果客户端死活不认。因为客户端只信任根 CA,它手里没有中间 CA 的公钥,也就没法验证签名。所以,服务器端一定要把完整的证书链发过去。
下面这张图,展示了证书链的完整信任路径。
3.4 CA 信任模型
CA 信任模型主要有这么几种。我刚开始做安全运维时,经常搞混。
| 模型 | 说明 | 典型场景 |
|---|---|---|
| 层次模型 | 根 CA → 中间 CA → 终端证书,单向信任链 | 互联网 PKI,最常用 |
| 网状模型 | 多个 CA 相互交叉认证 | 企业内部复杂网络 |
| 桥接模型 | 一个桥 CA 连接多个独立的 PKI 系统 | 跨组织合作 |
大多数场景下,我们用的是层次模型。原因很简单,管理简单,信任路径清晰。网状模型虽然灵活,但容易形成环路,维护成本很高。
注意: 层次模型里,根 CA 的安全是重中之重。一旦根 CA 私钥泄露,整个信任体系就崩塌了。我见过一个案例,一家公司的根 CA 被攻破,不得不吊销所有下级证书,重新搭建一套 PKI。
所以,根 CA 的私钥通常离线存储,放在机房保险柜或者硬件加密机里。只有签发中间 CA 证书时,才会拿出来用一下。
3.5 自签名证书
自签名证书,就是自己给自己签发的证书。说白了,自己当自己的 CA。
为什么需要它?
- 开发和测试环境,没必要花冤枉钱买商业证书。
- 内部系统,比如公司内部的 CI/CD 工具。
- 学习目的,理解证书结构。
生成自签名证书很简单,用 OpenSSL 就行。我最常用的命令是这个:
openssl req -x509 -newkey rsa:2048 -keyout server.key -out server.crt -days 365 -nodes
这行命令会生成一个 RSA 2048 位的密钥对,以及一个有效期为 365 天的自签名证书。
但要注意,自签名证书不会被浏览器信任。因为浏览器不认你这个「自封的 CA」。你访问一个自签名证书的网站,浏览器会弹出大大的警告。
我的做法: 在开发环境里,我会把自签名证书的根证书,手动导入到操作系统的信任存储里。这样浏览器就不会报错了。但生产环境千万别这么干,会被安全审计扣分的。
另外,自签名证书也分两种:一种是只签自己,另一种是自建根 CA,然后签中间证书。后者更接近真实的 CA 层次结构。我建议你做实验时,用第二种方式,能帮你更好地理解证书链。
嗯,这张证书的内容其实挺多的。核心就是:X.509 结构、证书链的逐级验证、CA 的信任模型,以及自签名证书的适用场景。把这些搞懂了,后面配置 TLS 心里就有底了。