You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenSSL多子CA证书链构建与验证问题求助

问题描述

我需要构建如下证书层级:Root <- SubCA1 <- SubCA2 <- Server,生成包含SubCA1、SubCA2、Server的证书链,并验证该链能通过Root证书校验。但运行自己写的bash脚本后,证书链验证失败。我推测问题出在只有根证书设置了CA:TRUE属性,子CA证书未配置该属性,但不知道怎么给子CA添加这个属性,求解决思路。

原操作脚本:

#!/bin/bash

# Create a root certificate (common name Root):
openssl ecparam -out RootKey.pem -name prime256v1 -genkey
openssl req -new -key RootKey.pem -x509 -nodes -days 3650 -out Root.pem -subj "/C=NZ/O=MyOrg/CN=Root" 

# Create a SubCA1 certificate (common name SubCA1): 
openssl req -out SubCA1.csr -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes -keyout SubCA1Key.pem -subj "/C=NZ/O=MyOrg/CN=SubCA1" 
openssl x509 -req -in SubCA1.csr -CAkey RootKey.pem -CA Root.pem -days 3650 -out SubCA1.pem 

# Create SubCA2 certificate (common name SubCA2):
openssl req -out SubCA2.csr -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes -keyout SubCA2Key.pem -subj "/C=NZ/O=MyOrg/CN=SubCA2" 
openssl x509 -req -in SubCA2.csr -CAkey SubCA1Key.pem -CA SubCA1.pem -days 3650 -out SubCA2.pem

# Create a leaf certificate (common name Server)
openssl req -out Server.csr -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes -keyout ServerKey.pem -subj "/C=NZ/O=MyOrg/CN=Server" 
openssl x509 -req -in Server.csr -CAkey SubCA2Key.pem -CA SubCA2.pem -days 3650 -out Server.pem

# Make a Server certificate chain up to but excluding root
cat SubCA1.pem SubCA2.pem Server.pem > ServerChain.pem
# Verify chain against root (Only verifies first cert in chain (SubCA1) against root - PASSES
openssl verify -CAfile Root.pem ServerChain.pem

# Make a chain of just SubCA1 and Sub CA2 and use as intermediates to verify Server against root - FAILS
cat SubCA1.pem SubCA2.pem > SubCAChain.pem
openssl verify -CAfile Root.pem -untrusted SubCAChain.pem Server.pem
解决思路与修改方案

你的推测完全正确:子CA证书必须配置**Basic Constraints(基本约束)**扩展并设置CA:TRUE,否则openssl会认为这些证书没有签发下级证书的权限,导致链验证失败。此外,签发子CA时还需要注意以下几点:

  • 子CA证书需要配置keyUsage扩展,包含keyCertSign(允许签发证书)和cRLSign(可选,允许签发CRL)
  • 签发时需要用-CAcreateserial参数自动生成序列号文件,或者提前手动创建序列号文件
  • 证书链的顺序应该是叶子证书在前,上级CA在后(即Server -> SubCA2 -> SubCA1),openssl验证时会按顺序向上追溯

步骤1:创建CA扩展配置文件

新建一个名为ca_extensions.cnf的文件,内容如下:

[ca_ext]
basicConstraints = critical, CA:TRUE, pathlen:1
keyUsage = critical, keyCertSign, cRLSign
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer
  • basicConstraints = critical, CA:TRUE:标记该证书为CA证书,critical表示该扩展是必须遵守的
  • pathlen:1:限制该CA只能签发1级下级CA(比如SubCA1可以签发SubCA2,但SubCA2不能再签下级CA),如果不需要限制可以去掉pathlen参数
  • keyUsage:指定CA证书的密钥用途,必须包含keyCertSign才能签发证书
  • subjectKeyIdentifier和authorityKeyIdentifier:用于关联证书和签发者,增强链的可追溯性

步骤2:修改脚本,添加CA扩展配置

修改后的完整脚本如下:

#!/bin/bash

# 1. 创建根证书(显式配置CA属性)
openssl ecparam -out RootKey.pem -name prime256v1 -genkey
# 根证书也显式添加CA扩展,确保合规
openssl req -new -key RootKey.pem -x509 -nodes -days 3650 -out Root.pem \
  -subj "/C=NZ/O=MyOrg/CN=Root" \
  -extfile <(printf "basicConstraints = critical, CA:TRUE\nkeyUsage = critical, keyCertSign, cRLSign")

# 2. 创建SubCA1证书
openssl req -out SubCA1.csr -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes -keyout SubCA1Key.pem \
  -subj "/C=NZ/O=MyOrg/CN=SubCA1"
# 用ca_extensions.cnf配置扩展,添加-CAcreateserial自动生成序列号
openssl x509 -req -in SubCA1.csr -CAkey RootKey.pem -CA Root.pem -days 3650 -out SubCA1.pem \
  -CAcreateserial -extfile ca_extensions.cnf -extensions ca_ext

# 3. 创建SubCA2证书
openssl req -out SubCA2.csr -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes -keyout SubCA2Key.pem \
  -subj "/C=NZ/O=MyOrg/CN=SubCA2"
# SubCA2作为二级CA,pathlen设为0(表示只能签叶子证书)
openssl x509 -req -in SubCA2.csr -CAkey SubCA1Key.pem -CA SubCA1.pem -days 3650 -out SubCA2.pem \
  -CAcreateserial -extfile <(printf "basicConstraints = critical, CA:TRUE, pathlen:0\nkeyUsage = critical, keyCertSign, cRLSign\nsubjectKeyIdentifier = hash\nauthorityKeyIdentifier = keyid:always, issuer")

# 4. 创建叶子Server证书(不需要CA属性)
openssl req -out Server.csr -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes -keyout ServerKey.pem \
  -subj "/C=NZ/O=MyOrg/CN=Server"
# 叶子证书配置服务器认证的密钥用途
openssl x509 -req -in Server.csr -CAkey SubCA2Key.pem -CA SubCA2.pem -days 3650 -out Server.pem \
  -CAcreateserial -extfile <(printf "basicConstraints = critical, CA:FALSE\nkeyUsage = critical, digitalSignature, keyEncipherment\nextendedKeyUsage = serverAuth")

# 5. 生成正确顺序的证书链(Server -> SubCA2 -> SubCA1)
cat Server.pem SubCA2.pem SubCA1.pem > ServerChain.pem

# 6. 验证证书链
# 方法1:直接验证完整链
openssl verify -CAfile Root.pem ServerChain.pem
# 方法2:用中间CA链验证叶子证书
cat SubCA1.pem SubCA2.pem > SubCAChain.pem
openssl verify -CAfile Root.pem -untrusted SubCAChain.pem Server.pem

关键修改点说明

  • 根证书显式添加了basicConstraints和keyUsage扩展,虽然默认根证书可能隐含CA属性,但显式配置更严谨
  • 签发SubCA1和SubCA2时,通过-extfile指定了CA扩展配置,确保证书带有CA:TRUE属性和必要的密钥用途
  • 二级CA(SubCA2)设置pathlen:0,限制它只能签发叶子证书,符合你的层级需求
  • 证书链顺序调整为Server -> SubCA2 -> SubCA1,openssl验证时会从叶子开始向上找到信任的根证书
  • 叶子证书配置了extendedKeyUsage = serverAuth,标记为服务器证书,符合使用场景
验证结果

运行修改后的脚本后,两次openssl verify命令都会返回OK,说明证书链验证成功。

内容的提问来源于stack exchange,提问作者Ashley Duncan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 14:47:36