3. 数字证书与CA

说到TLS,绕不开的就是数字证书。我刚开始接触这玩意儿的时候,也觉得不就是个文件嘛。后来被坑过几次,才明白这里面的门道有多深。

说白了,数字证书就是网络世界里的「身份证」。但它比身份证复杂得多。咱们这一章,就把证书的里里外外扒个干净。

3.1 X.509 证书是什么?

X.509 是一种国际标准,定义了公钥证书的格式。目前主流的是 X.509 v3 版本。几乎所有 HTTPS 网站用的都是它。

你打开浏览器,点那个小锁图标,看到的证书信息,就是 X.509 格式。我印象里,有一次排查一个双向认证失败的问题,查了两天,最后发现是证书里的扩展字段写错了。

证书的本质,就是把「公钥」和「身份信息」绑定在一起。谁来担保这种绑定关系呢?证书颁发机构——也就是 CA。

3.2 证书结构详解

一个标准的 X.509 v3 证书,包含以下核心字段。我建议你把这个表格背下来,排查问题的时候会很有用。

字段说明我的经验提醒
版本号目前主流是 v3v1/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 的证书,预装在操作系统或浏览器里。

校验过程是这样的:

  1. 用根 CA 的公钥,验证中间 CA 证书的签名。
  2. 用中间 CA 的公钥,验证服务器证书的签名。
  3. 如果都通过了,就信任服务器证书。

这就是一个典型的信任传递。你不需要信任每个网站,你只需要信任几个根 CA。

避坑指南: 我曾经在配置双向认证时,只发了服务器证书,没发中间证书链。结果客户端死活不认。因为客户端只信任根 CA,它手里没有中间 CA 的公钥,也就没法验证签名。所以,服务器端一定要把完整的证书链发过去。

下面这张图,展示了证书链的完整信任路径。

证书链信任模型 根 CA 中间 CA 1 中间 CA 2 网站证书 客户端证书 签发 签发 签发 签发 信任路径:根 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 心里就有底了。