4、自建CA与根证书:打造你的信任锚点

聊到mTLS,绕不开一个东西——CA。说白了,CA就是那个负责发身份证的机构。在公网场景里,你可以找Let's Encrypt、DigiCert这些商业CA。但在企业内部,尤其是微服务之间的mTLS通信,我强烈建议你自建CA。

为什么?因为根证书掌握在自己手里,你说了算。签发、吊销、续期,全流程可控。今天我们就来亲手搭建一个根CA。

4.1 根CA私钥:一切信任的起点

根CA私钥是整个PKI体系的命根子。它一旦泄露,你签发的所有证书都不再可信。所以,生成私钥这一步,必须认真对待。

我个人习惯用 openssl 来做这件事。命令很简单,但参数有讲究。

# 生成RSA 4096位私钥,使用AES-256加密
openssl genrsa -aes256 -out ca-key.pem 4096

这里我用了 -aes256,意味着私钥文件会被加密存储。每次使用私钥时,你都需要输入密码。嗯,这确实会麻烦一点,但安全系数高了一个档次。

⚠️ 私钥密码别搞丢

我曾经见过一个团队,把根CA私钥密码写在便签纸上贴在显示器边框上……后来那个密码被保洁阿姨当垃圾扔了。建议用密码管理器保管,或者至少放在保险柜里。

生成后的私钥文件长这样:

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,ABCD1234...
...(一堆Base64编码的内容)...
-----END RSA PRIVATE KEY-----

注意看文件头,有 ENCRYPTED 字样,说明私钥是加密的。如果你看到的是 BEGIN PRIVATE KEY 而没有加密标记,那就要小心了——私钥以明文存储,风险极高。

4.2 根自签名证书:信任链的顶端

有了私钥,接下来就是生成根证书。根证书是自签名的——也就是说,它自己证明自己可信。听起来有点循环论证,但这就是PKI的根基。

生成根证书的命令:

openssl req -x509 -new -nodes \
  -key ca-key.pem \
  -sha256 -days 3650 \
  -out ca-cert.pem \
  -subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/CN=My Root CA"

几个关键参数我解释一下:

  • -x509:输出自签名证书格式
  • -days 3650:有效期10年。根证书有效期一般设得长,5到10年都行
  • -sha256:摘要算法。别用SHA-1了,那玩意儿已经不安全了
  • -subj:证书主体信息。CN(Common Name)写个有辨识度的名字,比如"My Root CA"
💡 关于CN字段

根证书的CN其实没那么严格,但建议用英文,避免某些老旧系统对中文支持不好。我一般写成 "CompanyName Root CA 2025" 这种格式,方便识别。

生成的证书内容可以用这个命令查看:

openssl x509 -in ca-cert.pem -text -noout

你会看到证书的版本、序列号、签名算法、有效期、公钥信息等。其中 Issuer 和 Subject 字段是一样的——这就是自签名的特征。

4.3 CA策略文件:规矩得立好

光有私钥和证书还不够。你还需要一个策略文件,告诉OpenSSL:哪些证书能签,哪些不能签。这就像公司的规章制度,提前定好,避免后面乱套。

我常用的策略文件 ca.cnf 长这样:

[ ca ]
default_ca = CA_default

[ CA_default ]
# 数据库和序列号文件
database    = index.txt
serial      = serial

# 新证书存放目录
new_certs_dir = ./newcerts

# 默认策略
default_md  = sha256
default_days = 365
preserve    = no

# 策略匹配规则
policy      = policy_loose

[ policy_loose ]
# 国家必须匹配
countryName             = match
# 省份可选
stateOrProvinceName     = optional
# 组织必须匹配
organizationName        = match
# 组织单位可选
organizationalUnitName  = optional
# 通用名称必须提供
commonName              = supplied
# 邮箱可选
emailAddress            = optional

这里有个关键点:match 表示必须和根证书一致,supplied 表示必须提供但可以不同,optional 表示可有可无。

我个人建议,在内部环境里用 policy_loose 这种宽松策略。为什么?因为微服务的证书CN往往是服务名,比如 service-a.internal,它和根证书的CN肯定不一样。如果用严格策略(policy_match),那所有签发的证书CN都得和根证书一样,这显然不合理。

📋 初始化CA工作目录

在运行签发命令前,需要先创建几个文件:

mkdir -p ./newcerts
touch index.txt
echo 01 > serial

index.txt 是证书数据库,记录所有已签发证书的状态。serial 文件记录下一个证书的序列号。

4.4 根证书的保管:比金库还重要

根证书和私钥的保管,是整个mTLS体系中最重要的一环。我见过太多因为根证书管理不善导致的安全事故。

这里我总结了几条硬性规则:

保管对象 建议措施 绝对禁止
根CA私钥(加密后) 离线存储,放在U盘或HSM中,锁入保险柜 放在CI/CD服务器上、上传到Git仓库
根CA私钥密码 密码管理器 + 纸质备份(分开存放) 写在代码注释里、存在明文文件里
根证书(公钥部分) 可以分发到所有需要验证的客户端 无所谓,公钥本来就是公开的
CA策略文件 版本控制,记录变更历史 随意修改不通知团队

我曾经在一个客户现场,发现他们把根CA私钥直接放在Kubernetes的ConfigMap里。你想想看,ConfigMap默认是明文存储的,等于把保险柜钥匙挂在大门上。后来我帮他们重建了整个CA体系,折腾了两天。

还有一个容易被忽略的点:根证书的备份。私钥和证书至少要准备两份物理备份,放在不同地点。万一机房着火了,你还有另一份。

4.5 本章核心逻辑图

下面这张图展示了根CA的创建流程和信任关系:

根CA创建与信任链 根CA创建与信任链 1. 生成根CA私钥 openssl genrsa -aes256 2. 生成自签名证书 openssl req -x509 3. 配置CA策略文件 ca.cnf + index.txt 信任链结构 根证书(自签名) 中间CA(可选) 服务端/客户端证书 保管要求 私钥:离线存储、加密保管、双人控制 证书:可分发、定期检查有效期、到期前续签

从图中可以看到,根CA是整个信任链的锚点。所有下级证书的信任,最终都追溯到根证书。所以,根证书和私钥的保管,再怎么强调都不为过。

4.6 验证你的根CA

最后,验证一下你的根证书是否可用:

# 查看证书信息
openssl x509 -in ca-cert.pem -text -noout | grep -E "Subject:|Issuer:|Not Before|Not After"

# 验证自签名(自己验证自己)
openssl verify -CAfile ca-cert.pem ca-cert.pem

# 输出应该是:ca-cert.pem: OK

如果看到 OK,恭喜你,根CA已经搭建完成。接下来就可以用它来签发服务端和客户端证书了。

💡 一个小建议

根CA搭建完成后,建议把私钥文件复制到离线存储设备上,然后从工作机器上彻底删除。日常签发证书时,使用中间CA来做,根CA只在需要签发中间CA时才上线。这样即使中间CA被攻破,根CA仍然是安全的。