1. 使用 OpenSSL 生成自签名根 CA 证书
任务拆解:一张自签名根证书要满足什么
本例的目标是产出一个自签名根 CA 证书,它必须同时满足四个硬性条件:
- 自签名:证书的签发者(Issuer)与主体(Subject)完全相同,且用自身私钥完成签名。
- CA:TRUE:X.509 v3 扩展中
basicConstraints必须标记为 CA,否则它只能当终端实体证书,无法签发下级证书。 - 有效期可读:通过
openssl x509 -noout -dates能读出 notBefore / notAfter。 - 密钥用法正确:
keyUsage至少包含keyCertSign与cRLSign,这是 CA 证书的典型用法。
下面这张图把「输入参数 → 生成动作 → 证书内部结构 → 验证命令」串成一条可对照的链路,方便你在执行时逐项核对。
关键参数与命令逐项说明
下面给出可直接执行的完整命令序列。所有参数都在本例中定义,不依赖前文。
# 1. 生成 2048 位 RSA 私钥(本例不加密,便于聚焦证书本身)
openssl genrsa -out rootCA.key 2048
# 2. 生成自签名根证书,有效期 3650 天,使用 SHA-256 签名
openssl req -x509 -new -nodes \
-key rootCA.key \
-sha256 \
-days 3650 \
-out rootCA.crt \
-subj "/C=CN/ST=Beijing/L=Beijing/O=DemoOrg/CN=Demo Root CA" \
-extensions v3_ca \
-config <(cat /etc/ssl/openssl.cnf \
<(printf "\n[v3_ca]\nbasicConstraints=critical,CA:TRUE\nkeyUsage=critical,keyCertSign,cRLSign\nsubjectKeyIdentifier=hash\nauthorityKeyIdentifier=keyid:always"))
为什么必须显式指定
OpenSSL 默认的
-extensions v3_ca?OpenSSL 默认的
req -x509 不会自动加入 basicConstraints=CA:TRUE。如果不加这个扩展,生成的证书虽然能自签名,但会被浏览器和验证工具判定为「非 CA 证书」,无法用于签发下级证书。这是初学者最常见的坑。
验证与判读
生成后依次执行以下四条命令,逐项核对:
# 查看有效期
openssl x509 -in rootCA.crt -noout -dates
# 查看密钥用法
openssl x509 -in rootCA.crt -noout -ext keyUsage
# 查看基本约束
openssl x509 -in rootCA.crt -noout -ext basicConstraints
# 查看主题与签发者
openssl x509 -in rootCA.crt -noout -subject -issuer
| 检查项 | 期望输出 | 不通过时的典型原因 |
|---|---|---|
| 有效期 | notBefore 与 notAfter 相差约 3650 天 | 忘记 -days,默认 30 天 |
| keyUsage | 包含 keyCertSign 和 cRLSign | 未指定 v3_ca 扩展段 |
| basicConstraints | CA:TRUE | 未加 basicConstraints=critical,CA:TRUE |
| Subject / Issuer | 两者完全一致 | 误用了 req -new 而非 req -x509 |
安全提醒:本例使用
-nodes 生成无密码私钥,仅用于教学演示。生产环境的根 CA 私钥必须加密存储,并放在离线或受控环境中。私钥文件 rootCA.key 一旦泄露,整个信任链即告失效。
可复用的检查清单
- 私钥文件存在且为 RSA 2048:
openssl rsa -in rootCA.key -noout -text | head -1 - 证书为 X.509 v3:
openssl x509 -in rootCA.crt -noout -text | grep "Version" - 签名算法为 sha256WithRSAEncryption
- basicConstraints 标记为 critical 且 CA:TRUE
- keyUsage 标记为 critical 且含 keyCertSign、cRLSign
- Subject 与 Issuer 字段逐字相同