4、OpenSSL实战:安装、配置与根CA/中间CA证书生成

说实话,很多搞了几年证书的人,对OpenSSL还是「会用但不懂」。命令行敲得溜,但一问到配置文件里那几百行参数是干嘛的,就含糊了。

我个人习惯是:先把OpenSSL当成一个工具箱摸透,再谈企业级PKI。这一章,我们就从零开始,把OpenSSL装好、把配置文件读透、然后亲手生成一套根CA和中间CA。

本章核心目标:搭建一个可复用的两级CA体系,为后续的证书链故障诊断打下基础。

4.1 OpenSSL安装:别小看这一步

不同操作系统,安装方式略有差异。我建议你尽量用包管理器,别自己编译——除非你有特殊需求。

操作系统 安装命令 备注
Ubuntu/Debian sudo apt install openssl 一般系统自带,版本可能偏旧
CentOS/RHEL 7+ sudo yum install openssl RHEL 8/9 用 dnf
macOS brew install openssl 系统自带的是LibreSSL,建议用Homebrew装OpenSSL
Windows 下载安装包或WSL 我个人不推荐Windows原生跑OpenSSL,坑多

小提示:装完后跑一下 openssl version,确认版本号。我建议用 1.1.1 以上版本,3.0 更好。1.0.2 已经EOL了,别用了。

4.2 配置文件解读:OpenSSL的「灵魂」

OpenSSL的配置文件默认在 /etc/ssl/openssl.cnf(Linux)或 /usr/local/etc/openssl@3/openssl.cnf(macOS)。

你想想看,这个文件定义了CA怎么干活:密钥放哪、证书有效期多久、扩展字段填什么。不读懂它,你生成的证书就是「野路子」。

4.2.1 核心段落结构

配置文件分几个大段,我用表格给你拆开:

段落名 作用 我常改的参数
[ req ] 定义证书签名请求(CSR)的默认行为 default_bits、distinguished_name
[ ca ] 定义CA操作(签名、吊销)的默认配置 default_ca 指向哪个CA段
[ CA_default ] CA的具体工作目录、数据库、序列号文件 dir、database、serial
[ policy_match ] CA签名时对CSR字段的匹配策略 企业内一般用 policy_anything
[ v3_ca ] CA证书的X.509 v3扩展 basicConstraints、keyUsage
[ v3_req ] 终端证书的扩展 subjectAltName 必须配

注意:默认配置里 [ policy_match ] 要求国家、组织名必须匹配。我在项目中遇到过,用默认配置给不同部门的服务器签名,结果一直报错。后来改成 policy_anything 才解决。

4.2.2 我常用的自定义配置片段

嗯,这里我直接贴一段我自己的模板,你拿去改改就能用:

[ req ]
default_bits        = 4096
distinguished_name  = req_distinguished_name
string_mask         = utf8only
prompt              = no

[ req_distinguished_name ]
countryName             = CN
stateOrProvinceName     = Beijing
localityName            = Beijing
organizationName        = MyCompany
organizationalUnitName  = IT Security
commonName              = MyCompany Root CA

[ v3_ca ]
basicConstraints       = critical, CA:TRUE
keyUsage               = critical, keyCertSign, cRLSign
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid:always,issuer

注意 prompt = no,这样生成CSR时不会弹交互式问答,适合脚本化。我所有自动化流程都用这个。

4.3 生成根CA证书

根CA是信任链的锚点。它一旦泄露,整个PKI就完了。所以,根CA的私钥一定要保护好。

4.3.1 创建目录结构

我习惯这样组织文件:

mkdir -p ~/myCA/rootCA/{certs,crl,newcerts,private}
chmod 700 ~/myCA/rootCA/private
touch ~/myCA/rootCA/index.txt
echo 1000 > ~/myCA/rootCA/serial
  • certs:存放已签发的证书
  • crl:证书吊销列表
  • newcerts:OpenSSL自动生成的证书副本
  • private:私钥目录,权限必须700
  • index.txt:证书数据库,OpenSSL用它追踪已签证书
  • serial:序列号计数器,从1000开始

4.3.2 生成根CA私钥和证书

先搞私钥,再搞证书。两步走:

# 第一步:生成RSA私钥,4096位,带AES-256加密
openssl genrsa -aes256 -out ~/myCA/rootCA/private/ca.key.pem 4096

# 第二步:生成自签名根证书,有效期20年
openssl req -config openssl.cnf \
    -key ~/myCA/rootCA/private/ca.key.pem \
    -new -x509 -days 7300 -sha256 \
    -extensions v3_ca \
    -out ~/myCA/rootCA/certs/ca.cert.pem

经验之谈:根CA有效期我一般设10-20年。太短了要频繁换根,太长了万一算法被破解也麻烦。20年是个折中。

验证一下证书内容:

openssl x509 -in ~/myCA/rootCA/certs/ca.cert.pem -text -noout

重点关注 Basic Constraints: CA:TRUE 和 Key Usage: Certificate Sign, CRL Sign。缺了这两个,它就不是一个合格的CA证书。

4.4 生成中间CA证书

根CA不能直接签终端证书。为什么?因为根CA私钥一旦用于日常签名,暴露风险太大。中间CA就是那个「干活的人」。

4.4.1 创建中间CA目录

mkdir -p ~/myCA/intermediateCA/{certs,crl,newcerts,private,csr}
chmod 700 ~/myCA/intermediateCA/private
touch ~/myCA/intermediateCA/index.txt
echo 1000 > ~/myCA/intermediateCA/serial
echo 1000 > ~/myCA/intermediateCA/crlnumber

4.4.2 生成中间CA私钥和CSR

# 私钥
openssl genrsa -aes256 \
    -out ~/myCA/intermediateCA/private/intermediate.key.pem 4096

# CSR
openssl req -config intermediate_openssl.cnf \
    -key ~/myCA/intermediateCA/private/intermediate.key.pem \
    -new -sha256 \
    -out ~/myCA/intermediateCA/csr/intermediate.csr.pem

注意这里用的是 intermediate_openssl.cnf,它和根CA的配置略有不同——basicConstraints 要设 CA:TRUE, pathlen:0,限制中间CA下面不能再有CA。

4.4.3 用根CA签名中间CA证书

这一步是关键。根CA给中间CA签名,形成信任链:

openssl ca -config root_openssl.cnf \
    -extensions v3_intermediate_ca \
    -days 3650 -notext -md sha256 \
    -in ~/myCA/intermediateCA/csr/intermediate.csr.pem \
    -out ~/myCA/intermediateCA/certs/intermediate.cert.pem

签名时,OpenSSL会检查CSR里的字段是否匹配策略。如果报错,八成是 policy 没配对。

我曾经遇到过一个问题:签名时提示「TXT_DB error number 2」。查了半天,原来是 index.txt 里已经有重复的序列号。清空 index.txt 重新来就好了。

4.5 验证证书链

证书生成完,必须验证链是否完整。命令很简单:

openssl verify -CAfile ~/myCA/rootCA/certs/ca.cert.pem \
    ~/myCA/intermediateCA/certs/intermediate.cert.pem

如果输出 intermediate.cert.pem: OK,说明链没问题。

如果报 unable to get local issuer certificate,说明根证书没找到或者中间证书的签发者不匹配。

4.6 本章知识体系图

下面这张SVG图,把根CA和中间CA的生成流程、文件关系画清楚了。建议你对照着操作:

根CA与中间CA生成流程 根CA私钥 根CA自签名证书 中间CA私钥 中间CA CSR 中间CA证书(已签名) 根CA签名(openssl ca) 关键说明: 1. 根CA私钥必须离线存储,仅在签名中间CA时使用。 2. 中间CA私钥用于日常签发终端证书,可在线使用。 3. 根CA证书有效期建议10-20年,中间CA证书建议5年。 4. 验证链:openssl verify -CAfile rootCA.pem intermediateCA.pem

4.7 避坑指南

最后,我把自己踩过的坑列一下,你遇到了直接对照:

  • 私钥权限:private/ 目录一定要 chmod 700,私钥文件 600。我曾经因为权限不对,导致自动化脚本读不到私钥,半夜被叫起来修。
  • 序列号重复:如果 serial 文件内容被重置或重复,签名会失败。每次签名前检查一下 cat serial。
  • index.txt 损坏:不要手动编辑 index.txt,格式错了OpenSSL就不认了。用 openssl ca 自带的命令操作。
  • 证书扩展缺失:终端证书必须带 subjectAltName,否则浏览器会报错。CA证书必须带 CA:TRUE。
  • 路径长度限制:中间CA的 pathlen:0 限制了它不能再签发下级CA。如果你需要多级CA,记得调整这个值。