证书生成流程及密钥关联性
生成根证书(自签名证书)
私钥生成
openssl genrsa -out CA-A.key 2048 |
生成根证书私钥 CA-A.key(2048位RSA密钥),仅用于签发下级证书
公钥与证书生成
openssl req -x509 -new -key CA-A.key -out CA-A.crt -days 3650 |
通过私钥生成自签名根证书CA-A.crt,内含公钥和身份信息,有效期10年
生成中间证书B(由根证书签发)
中间私钥生成
openssl genrsa -out Cert-B.key 2048 |
生成中间证书私钥 Cert-B.key,用于签发终端证书或下一级中间证书
生成证书签名请求(CSR)
openssl req -new -key Cert-B.key -out Cert-B.csr |
创建包含公钥和身份信息的请求文件 Cert-B.csr
根证书签发中间证书
openssl x509 -req -in Cert-B.csr -CA CA-A.crt -CAkey CA-A.key -out Cert-B.crt -days 365 -CAcreateserial |
使用根证书私钥对中间证书签名,生成Cert-B.crt,其公钥由 Cert-B.key派生
生成终端证书C(由中间证书签发)
终端私钥生成
openssl genrsa -out Cert-C.key 2048 |
生成终端私钥Cert-C.key,用于服务端或客户端加密通信
生成终端CSR:
openssl req -new -key Cert-C.key -out Cert-C.csr |
包含终端公钥和域名/IP等信息的请求文件
中间证书签发终端证书
openssl x509 -req -in Cert-C.csr -CA Cert-B.crt -CAkey Cert-B.key -out Cert-C.crt -days 365 -CAcreateserial |
中间证书私钥对终端证书签名,生成,其公钥由Cert-C.key派生
关键关联总结
组件 | 生成来源 | 作用场景 | 安全性要求 |
---|---|---|---|
根证书私钥 | 手动生成(openssl) | 签发中间证书 | 最高(建议离线存储) |
中间证书私钥 | 中间证书生成流程 | 签发终端证书 | 高(限制访问权限) |
终端私钥 | 终端证书生成流程 | 加密通信/生成签名 | 中(服务器端存储) |
证书 | 由上级私钥签发 | 公钥合法性验证与身份认证 | 需保护完整性 |
验证证书链时,需合并根证书和中间证书(cat CA-A.crt Cert-B.crt > chain.crt
),确保终端证书的信任链完整25。
证书有效性检查
证书有效期验证
检查证书时间范围
使用工具(如
openssl x509 -in cert.crt -dates -noout
)查看证书的 生效时间(notBefore
)和 失效时间(notAfter
),确保当前时间在有效期内12。示例输出:
textCopy CodenotBefore=Mar 5 00:00:00 2025 GMT
notAfter=Mar 5 00:00:00 2026 GMT
验证证书链有效期
- 根证书、中间证书和终端证书均需满足有效期要求,任一证书过期均会导致链式失效25。
证书链完整性验证
信任链回溯
终端证书的合法性需依赖完整的证书链(根证书 → 中间证书 → 终端证书)。
通过合并根证书和中间证书验证链式签名:
openssl verify -CAfile <(cat CA-Root.crt Intermediate.crt) Server.crt
若输出OK,则信任链完整
openssl verify -CAfile <(cat CA-A.crt Cert-B.crt) Cert-C.crt
自签名根证书验证
- 根证书需为自签名且存在于本地信任存储中(如系统或浏览器的受信任根证书列表)。
签名合法性验证
验证签发者签名
使用上级证书的公钥验证当前证书的签名是否合法。
OpenSSL 示例(验证中间证书是否由根证书签发):
openssl verify -CAfile CA-A.crt Cert-B.crt
若返回OK,则签名有效
检查证书用途
- 确认证书的扩展字段(如
X509v3 Key Usage
和X509v3 Extended Key Usage
)符合预期用途(如服务器认证、代码签名等)。
- 确认证书的扩展字段(如
证书撤销状态检查
CRL(证书撤销列表)查询
从证书中提取 CRL 分发点(
X509v3 CRL Distribution Points
),下载 CRL 文件并检查证书是否被撤销。OpenSSL 示例:
openssl crl -inform DER -in revoked.crl -text -noout
OCSP(在线证书状态协议)实时验证
使用 OCSP 服务实时验证证书状态:
openssl ocsp -issuer Intermediate.crt -cert Server.crt -url http://ocsp.example.com -text
若返回good,则证书未被撤销
完整的校验方法
# 将证书按顺序合并(C、B、A) |
-CAfile rootA.pem
- 作用:指定受信任的根证书(Root CA)。
- 逻辑:
- OpenSSL 将
rootA.pem
视为信任锚点(Trust Anchor)。 - 根证书必须自签名且存在于系统的信任存储中(或通过
-CAfile
显式指定)。
- OpenSSL 将
-untrusted intermediateB.pem
- 作用:提供中间证书(Intermediate CA),但该证书本身不受自动信任。
- 逻辑:
- OpenSSL 会用
intermediateB.pem
构建证书链,但不会直接信任它。 - 中间证书的合法性需通过根证书
rootA.pem
的签名验证。
- OpenSSL 会用
- 注意:
-untrusted
参数仅用于传递中间证书,不可省略。
certificateC.pem
- 作用:待验证的终端实体证书(End-Entity Certificate)。
- 逻辑:
- OpenSSL 会检查
certificateC.pem
的签名是否由intermediateB.pem
的私钥签发。 - 最终通过根证书
rootA.pem
验证整个链的合法性。
- OpenSSL 会检查
Q1: 为什么要用
-untrusted
参数?- 回答:中间证书本身不可被自动信任,必须通过根证书验证其合法性。
-untrusted
仅告诉 OpenSSL 使用这些证书来构建链,但不会直接信任它们。
Q2: 证书顺序是否重要?
- 合并证书链时:必须按从终端证书到根证书的顺序(
C -> B -> A
)。 - 使用
-untrusted
时:无需严格顺序,OpenSSL 会自动匹配颁发者(Issuer)和主题(Subject)。
Q3: 如果缺少中间证书会发生什么?
- OpenSSL 会报错:
unable to get issuer certificate
,表示无法找到链中的中间环节。
Q4: 如何验证其他格式的证书(如 DER 格式)?
使用
-inform DER
参数指定格式:openssl verify -CAfile rootA.der -inform DER ...
扩展场景
验证 HTTPS 服务器的证书链
openssl s_client \ |
- 通过
s_client
连接服务器并实时验证证书链。
检查证书吊销状态(OCSP)
openssl ocsp \ |
- 使用 OCSP 协议检查证书是否被吊销。
一个完整的校验场景
有一个根证书A,根据根证书A生成的中间证书B,根据中间证书B生成的证书C,这些证书都是crt格式,怎么校验这三个证书的有效性
验证证书C的签发关系
# 检查证书C是否由中间证书B签发 |
- 若输出
Cert-C.crt: OK
,表示证书C的签发者为中间证书B,且签名有效。
验证中间证书B的签发关系
# 检查中间证书B是否由根证书A签发 |
- 若输出
Cert-B.crt: OK
,表示中间证书B由根证书A签发。
验证证书链完整性
# 合并中间证书B和根证书A到链文件(chain.pem) |
- 若输出
Cert-C.crt: OK
,表示整个证书链可信。
手动验证签发者与主题匹配
# 查看证书C的签发者(Issuer) |
验证有效期
# 检查所有证书的有效期 |
- 需确保所有证书的
notBefore
和notAfter
时间覆盖当前时间
工具与代码示例
验证方式 | 工具/代码示例 |
---|---|
有效期检查 | openssl x509 -in cert.crt -dates -noout |
证书链验证 | openssl verify -CAfile chain.crt Server.crt |
签名合法性 | openssl verify -CAfile CA-Root.crt Intermediate.crt |
CRL/OCSP验证 | openssl crl 或 openssl ocsp 命令 |
证书生成实例解析
CI证书生成
生成 ECC 私钥
openssl ecparam -name prime256v1 -genkey -out ci_sk.pem |
作用:生成基于椭圆曲线
prime256v1
(即 NIST P-256 曲线)的 ECC 私钥。关键参数:
-name prime256v1
:指定椭圆曲线类型(P-256 是广泛使用的安全曲线)。-genkey
:生成私钥(默认生成 PEM 格式)。-out ci_sk.pem
:将私钥保存到文件ci_sk.pem
(PEM 编码,包含-----BEGIN EC PRIVATE KEY-----
头)
生成自签名 X.509 证书
openssl req -config ci_csr.cnf -key ci_sk.pem -new -x509 -days 365 -sha256 -set_serial 01 -extensions extend -out ci_cert.pem |
作用:直接生成自签名证书(跳过 CSR 步骤),使用上一步生成的私钥签名。
关键参数:
-config ci_csr.cnf
:指定配置文件(定义证书主题、扩展字段等)。-key ci_sk.pem
:使用ci_sk.pem
中的私钥对证书签名。-x509
:生成 X.509 自签名证书(而非证书请求 CSR)。-days 365
:证书有效期 1 年。-sha256
:使用 SHA-256 哈希算法签名。-set_serial 01
:设置证书序列号为01
(十六进制需加前缀0x
,如0x01
)。-extensions extend
:启用配置文件中[extend]
段的扩展字段(如密钥用途、主题别名等)。-out ci_cert.pem
:输出证书到ci_cert.pem
(PEM 格式)
配置文件 ci_csr.cnf
的作用
假设配置文件内容如下
[req] |
核心功能:
[dn]
段:定义证书主题信息(如域名、组织等)。- [extend]段:配置扩展字段:
basicConstraints = CA:FALSE
:声明非 CA 证书(不可签发下级证书)。keyUsage
:定义密钥用途(如签名、加密)。subjectAltName
:指定证书支持的域名/IP(多域名或泛域名证书需在此配置)
中间证书生成
生成 ECC 私钥
openssl ecparam -name prime256v1 -genkey -out eum_sk.pem |
作用:生成基于椭圆曲线
prime256v1
(NIST P-256)的 ECC 私钥。关键参数:
-name prime256v1
:指定椭圆曲线类型(安全且广泛支持)。-genkey
:直接生成私钥(等价于-param_enc explicit
+-noout
)。-out eum_sk.pem
:将私钥保存到eum_sk.pem
(PEM 格式,包含-----BEGIN EC PRIVATE KEY-----
头)。
输出文件:
eum_sk.pem
:ECC 私钥文件(需严格保密)。
生成证书签名请求(CSR)
openssl req -new -nodes -sha256 -config eum_input_csr.cnf -key eum_sk.pem -out eum_csr.cnf |
- 作用:使用私钥生成 CSR,用于向 CA 申请证书。
关键参数:
-new
:创建新的 CSR。-nodes
:不加密私钥(若省略此参数,默认会加密私钥,但此处已通过-key
指定私钥文件,因此-nodes
可能冗余)。-sha256
:签名哈希算法为 SHA-256。-config eum_input_csr.cnf
:指定 CSR 配置文件(定义主题信息、扩展字段等)。-key eum_sk.pem
:使用上一步生成的私钥对 CSR 签名。-out eum_csr.cnf
:输出 CSR 到eum_csr.cnf
(通常扩展名为.csr
,此处可能为笔误)。
配置文件
eum_input_csr.cnf
示例:iniCopy Code[req]
distinguished_name = dn
req_extensions = v3_req
prompt = no
[dn]
CN = My Device # 通用名称(如设备域名)
O = IoT Company # 组织名称
C = CN # 国家代码
[v3_req]
keyUsage = digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = device.example.com
IP.1 = 10.0.0.1输出文件:
eum_csr.cnf
:证书签名请求文件(包含公钥和主题信息)。
使用 CA 签发证书
openssl x509 -req -in eum_csr.cnf -CA ci_cert.pem -CAkey ci_sk.pem -set_serial 02 -days 365 -sha256 -extfile eum_ext.cnf -out eum_cert.pem |
作用:用 CA 的私钥(
ci_sk.pem
)和证书(ci_cert.pem
)对 CSR 签名,生成终端实体证书。关键参数:
-req
:输入文件是 CSR(而非证书)。-in eum_csr.cnf
:指定输入的 CSR 文件(同上,扩展名可能应为.csr
)。-CA ci_cert.pem
:指定 CA 的证书文件。-CAkey ci_sk.pem
:指定 CA 的私钥文件(用于签名)。-set_serial 02
:设置证书序列号为02
(十进制,十六进制需加0x
前缀,如0x02
)。-days 365
:证书有效期为 1 年。-sha256
:签名哈希算法为 SHA-256。-extfile eum_ext.cnf
:指定扩展字段配置文件(如主题备用名称、密钥用途等)。-out eum_cert.pem
:输出最终证书到eum_cert.pem
(PEM 格式)。
扩展文件 eum_ext.cnf
示例:
basicConstraints = CA:FALSE |
输出文件:
eum_cert.pem
:签发的 X.509 证书(包含公钥、主题信息和 CA 签名)。
流程总结
生成私钥 → 2. 生成 CSR → 3. CA 签发证书
- 文件关系:
- 私钥(
eum_sk.pem
)生成公钥(嵌入在 CSR 中)。 - CA 用私钥(
ci_sk.pem
)对 CSR(eum_csr.cnf
)签名,生成证书(eum_cert.pem
)
- 私钥(
证书的不同格式
证书格式的区别与共同点
核心编码标准
- PEM(Privacy-Enhanced Mail):
- 特点:Base64 编码的 ASCII 文本文件,包含
-----BEGIN/END xxx-----
头尾标记(如CERTIFICATE
、PRIVATE KEY
)12。 - 扩展名:
.pem
、.crt
、.cer
、.key
。 - 用途:存储证书、私钥、CSR 等,兼容性强,可文本编辑12。
- 特点:Base64 编码的 ASCII 文本文件,包含
- DER(Distinguished Encoding Rules):
- 特点:二进制格式,体积小,不可直接阅读,常用于 Java 和 Windows 系统24。
- 扩展名:
.der
、.cer
。
常见文件类型
扩展名 | 内容类型 | 编码格式 | 典型用途 |
---|---|---|---|
.key |
私钥 | PEM 或 DER | 存储非对称加密私钥 |
.crt |
证书 | PEM 或 DER | 存储公钥证书(X.509) |
.pem |
证书/私钥/CSR | PEM(Base64) | 通用存储格式 |
.der |
证书/私钥 | DER(二进制) | 系统特定场景(如 Java) |
.csr |
证书签名请求 | PEM 或 DER | 向 CA 申请证书 |
.pfx /.p12 |
证书+私钥(PKCS#12) | 二进制 | 多用途加密容器(含密码保护)25 |
共同点
- 内容本质:均基于 ASN.1 数据结构定义45。
- 编码关系:PEM 是 DER 的 Base64 文本包装,二者可互相转换14。
- 密钥与证书分离:私钥(
.key
)与证书(.crt
)通常独立存储,但 PKCS#12(.pfx
)可合并存储25。
格式转换方法(基于 OpenSSL)
PEM ↔ DER 互转
证书转换
# PEM 转 DER |
私钥转换
# PEM 转 DER |
注:RSA 私钥使用 openssl rsa
命令。
私钥格式转换(PKCS#1 ↔ PKCS#8)
PKCS#1(传统格式)转 PKCS#8(通用格式)
openssl pkcs8 -topk8 -in pkcs1.key -out pkcs8.key -nocrypt |
PKCS#1 头尾标记为 -----BEGIN RSA PRIVATE KEY-----
,PKCS#8 为 -----BEGIN PRIVATE KEY-----
34。
合并证书与私钥为 PKCS#12(.pfx
)
openssl pkcs12 -export -in cert.pem -inkey key.pem -out bundle.pfx |
注:需设置密码保护,适用于 Windows 和 Java 环境25。
提取 PKCS#12 中的证书/私钥
# 提取证书 |
关键注意事项
扩展名与编码无关:
.crt
和.cer
可能是 PEM 或 DER 编码,需通过文件内容判断。
私钥安全性:
- PEM 格式私钥建议加密存储(如添加
-aes256
参数)。
兼容性问题:
- DER 格式在跨平台传输时需注意二进制兼容性,PEM 更通用。
ASN.1 结构验证:
- 使用
openssl asn1parse -in file.der
可解析 DER 文件结构
证书链的生成与校验
生成证书链(根证书A → 证书B → 证书C)
生成根证书A
# 生成根证书私钥 |
关键配置:
- 根证书的
basicConstraints
必须为CA:TRUE
,表示可签发下级证书 。 - 默认生成的证书已包含
CA:TRUE
,无需额外配置扩展文件 。
生成中间证书B(由根证书A签发)
# 生成中间证书B的私钥 |
关键配置:
- 中间证书B的
basicConstraints
必须包含CA:TRUE
,允许继续签发下级证书 。 keyUsage
需包含keyCertSign
(允许签发证书)和cRLSign
(允许签发吊销列表)。
生成终端证书C(由中间证书B签发)
# 生成终端证书C的私钥 |
关键配置:
- 终端证书C的
basicConstraints
应为CA:FALSE
(默认值,表示不可签发下级证书)。 - 若需支持HTTPS,需包含
subjectAltName
(如域名或IP地址)。
构建证书链文件
# 合并证书链(根证书A → 中间证书B → 终端证书C) |
说明:
- 证书链顺序为:终端证书 → 中间证书 → 根证书 。
- 服务器部署时需将
chain.pem
与私钥一起配置(如Nginx的ssl_certificate
指令)。
验证证书链有效性
验证单个证书与签发者
bashCopy Code# 验证终端证书C是否由中间证书B签发 |
验证完整证书链
bashCopy Code# 使用根证书A验证整个链 |
预期输出:
- 若显示
certC.crt: OK
,表示链完整且有效 。
查看证书链结构
openssl x509 -in certC.crt -text -noout |
输出内容:
- 签发者(Issuer)应为中间证书B的主题(Subject)。
- 中间证书B的签发者应为根证书A的主题 。
注意事项
- 配置文件路径:
- 若未指定
-config
,默认使用系统配置文件(如/etc/ssl/openssl.cnf
),需确保路径正确 。
- 若未指定
- 密钥权限:
- 私钥文件(
.key
)需设置严格权限(如chmod 400
)。
- 私钥文件(
- 证书扩展字段:
- 中间证书必须包含
CA:TRUE
和keyCertSign
,否则无法签发下级证书 。
- 中间证书必须包含
- 证书链顺序:
- 部署时证书链文件必须按终端 → 中间 → 根的顺序排列
参考文档:
https://learn.microsoft.com/zh-cn/azure/application-gateway/self-signed-certificates