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
相关产品推荐
相关产品推荐

