4、根证书颁发机构(CA)搭建:生成CA私钥、生成CA自签名根证书、配置CA工作目录、验证根证书

说实话,搭建自己的根CA,是很多人学习PKI时最兴奋的一步。我记得自己第一次在实验室里敲完命令,看到那个自签名证书生成成功时,心里还挺有成就感的。但后来在生产环境里踩过几次坑,才明白这一步看似简单,实则处处是细节。

咱们今天就把根CA搭建这件事,掰开揉碎了讲清楚。你跟着我走一遍,以后不管是在内网做设备认证,还是给微服务配mTLS,心里都有底。

4.1 整体流程概览

搭建根CA,说白了就是四步走:

  1. 生成CA私钥 —— 这是CA的“身份证”,必须保管好
  2. 生成自签名根证书 —— 用私钥给自己签一张证书
  3. 配置CA工作目录 —— 让OpenSSL知道文件放哪、怎么管理
  4. 验证根证书 —— 确认证书能用、没毛病

这四步环环相扣。私钥丢了,证书就是废纸;目录配错了,后面签发子证书时会报一堆莫名其妙的错。我见过有人跳过第三步,直接手动管理文件,结果三个月后自己都找不到证书序号文件在哪。

根CA搭建四步流程 ① 生成CA私钥 openssl genrsa ② 自签名根证书 openssl req -x509 ③ 配置工作目录 index.txt / serial ④ 验证根证书 openssl x509 -text ⚠ 关键原则 私钥必须离线保管,工作目录结构一旦确定不要随意改动

4.2 生成CA私钥

私钥是CA的命根子。我习惯用 aes256 加密私钥文件,这样就算文件泄露了,没有密码也白搭。

核心命令:

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

执行后会让你输入一个密码。这里我多说一句:密码别用生日、公司名这种。我在一个项目里见过有人设了 ca123456,结果被内部审计直接打回。建议用至少16位,大小写+数字+特殊字符。

我的习惯:私钥文件权限设为 400(仅所有者可读)。曾经有个同事把私钥权限设成 644,被CI/CD工具误读到日志里……嗯,那场面挺尴尬的。

chmod 400 ca-key.pem

4.3 生成自签名根证书

有了私钥,下一步就是给自己发一张“身份证”。这里要用到 openssl req 命令,加上 -x509 参数表示自签名。

生成根证书:

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

参数说明:

参数 含义 建议值
-days 3650 证书有效期(天) 根证书建议10年(3650天)
-subj 证书主体信息 CN必须唯一标识你的CA
-x509 生成自签名证书 根CA必须用此参数

注意:根证书的有效期不要设太短。你想想看,如果根证书过期了,它下面签发的所有子证书都会失效。我建议至少10年,甚至20年也行。但别设成 -days 0,那证书当天就过期……别问我怎么知道的。

4.4 配置CA工作目录

这一步很多人会忽略,但恰恰是生产环境里最容易出问题的地方。OpenSSL需要一个标准的工作目录结构来管理证书签发记录。

我个人习惯用 /root/ca 作为根目录,结构如下:

mkdir -p /root/ca/{certs,crl,newcerts,private}
chmod 700 /root/ca/private
touch /root/ca/index.txt
echo 1000 > /root/ca/serial

每个目录的用途:

目录/文件 作用
certs/ 存放已签发的证书文件
crl/ 存放证书吊销列表
newcerts/ OpenSSL自动生成的证书副本
private/ 存放CA私钥(权限必须700)
index.txt 证书签发数据库,记录每张证书的状态
serial 下一个证书的序列号

避坑指南:我曾经在配置 openssl.cnf 时,忘了指定 dir 路径,结果OpenSSL默认用当前目录。后来签了50多张证书,想吊销一张时发现 index.txt 是空的……从那以后,我每次建CA都会先检查 openssl.cnf 里的路径配置。

这里给一份最简的 openssl.cnf 配置,放在 /root/ca/openssl.cnf:

[ ca ]
default_ca = CA_default

[ CA_default ]
dir               = /root/ca
certs             = $dir/certs
crl_dir           = $dir/crl
new_certs_dir     = $dir/newcerts
database          = $dir/index.txt
serial            = $dir/serial
private_key       = $dir/private/ca-key.pem
certificate       = $dir/ca-cert.pem
default_md        = sha256
policy            = policy_loose

[ policy_loose ]
countryName             = optional
stateOrProvinceName     = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

4.5 验证根证书

证书生成完了,目录也配好了,最后一步就是验证。别偷懒,这一步能帮你发现80%的配置错误。

验证命令:

# 查看证书基本信息
openssl x509 -in ca-cert.pem -text -noout

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

重点关注输出中的几个字段:

  • Issuer 和 Subject 必须相同 —— 这是自签名的标志
  • Validity 日期范围是否正确
  • Signature Algorithm 应该是 sha256WithRSAEncryption
  • X509v3 Basic Constraints 必须包含 CA:TRUE

重要:如果 openssl verify 返回 error 18 at 0 depth lookup: self signed certificate,别慌。这是根证书自签名的正常提示,表示“这个证书是自己签自己,不是由上级CA签发的”。只要没有 error 10(证书过期)或 error 20(无法获取本地颁发者证书),就没问题。

我习惯再用一条命令确认证书的CA能力:

openssl x509 -in ca-cert.pem -noout -ext basicConstraints

输出应该包含 CA:TRUE。如果没有,说明你生成证书时忘了加扩展属性,后面用它签发的子证书会不被浏览器或操作系统信任。

4.6 小结

到这步,你的根CA就搭好了。私钥在 private/ 里锁着,根证书在根目录下躺着,工作目录结构清晰,验证也通过了。说实话,这套流程我用了好几年,从实验室到生产环境都没出过岔子。

嗯,这里要再啰嗦一句:根CA的私钥最好离线存储。我在生产环境里会把私钥放到加密U盘里,只在需要签发中间CA时才挂载。平时服务器上只留根证书,不留私钥。这样就算服务器被攻破,攻击者也拿不到你的CA私钥。