OpenSSL子CA签发含SAN字段的网站证书失败问题咨询
问题背景与现象
原环境基于Microsoft Certificate Authority搭建PKI架构:根CA脱离域并处于关机状态,子CA加入域,通过IIS提供CRL服务并为域内计算机签发证书。现计划通过Linux+OpenSSL复刻该环境,核心目标是为内部网站签发证书。
目前已完成自签名根CA、根CA签发的子CA的创建,证书链验证正常,但在签发带**Subject Alternative Name(SAN)**字段的网站证书时遇到问题:
- 使用以下命令生成的CSR中包含正确的SAN字段:
openssl req -nodes -new -newkey rsa:4096 \ -keyout test3.psc.local.key \ -out test3.psc.local.csr \ -addext "subjectAltName = DNS:test3.psc.local" \ -subj "/C=ES/ST=Barcelona/L=Barcelona/O=GRG-CA/OU=GRG-CA/emailAddress=your@email.dot/CN=test3.psc.local/"
通过openssl x509 -noout -text -in test3.psc.local.csr检查,确认SAN字段存在且值正确。
- 使用子CA签发证书后,生成的证书缺失SAN字段,导致Chrome、Firefox等主流浏览器不信任该证书,仅IE11可正常识别:
openssl ca -config intermediate/sub-ca-openssl.cnf \ -extensions server_cert \ -days 375 -notext -md sha512 \ -in /root/ca/test3.psc.local.csr \ -out /root/ca/test3.psc.local.crt
子CA配置文件内容如下:
[ ca ] default_ca = CA_default [ CA_default ] dir = /root/ca/intermediate certs = $dir/certs crl_dir = $dir/crl new_certs_dir = $dir/newcerts database = $dir/subordinate-ca-database.txt serial = $dir/serial RANDFILE = $dir/private/.rand private_key = $dir/private/intermediate.key.pem certificate = $dir/certs/intermediate.cert.pem crlnumber = $dir/crlnumber crl = $dir/crl/intermediate.crl.pem crl_extensions = crl_ext default_crl_days = 365 default_md = sha512 name_opt = ca_default cert_opt = ca_default default_days = 5840 preserve = no policy = subca_policy [ subca_policy ] countryName = optional stateOrProvinceName = optional localityName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional [ req ] default_bits = 4096 distinguished_name = req_distinguished_name string_mask = utf8only default_md = sha512 x509_extensions = v3_ca [ req_distinguished_name ] countryName = Country Name (2 letter code) stateOrProvinceName = State or Province Name localityName = Locality Name 0.organizationName = Organization Name organizationalUnitName = Organizational Unit Name commonName = Common Name emailAddress = Email Address # Optionally, specify some defaults. countryName_default = ES stateOrProvinceName_default = Barcelona localityName_default = Barcelona 0.organizationName_default = GRG-CA organizationalUnitName_default = GRG-CA #emailAddress_default = [ v3_ca ] # Extensions for a typical CA (`man x509v3_config`). subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer basicConstraints = critical,CA:true keyUsage = critical, digitalSignature, cRLSign, keyCertSign [ v3_intermediate_ca ] # Extensions for a typical intermediate CA (`man x509v3_config`). subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer basicConstraints = critical, CA:true, pathlen:0 keyUsage = critical, digitalSignature, cRLSign, keyCertSign [ usr_cert ] # Extensions for client certificates (`man x509v3_config`). basicConstraints = CA:FALSE nsCertType = client, email nsComment = "OpenSSL Generated Client Certificate" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = clientAuth, emailProtection [ server_cert ] # Extensions for server certificates (`man x509v3_config`). basicConstraints = CA:FALSE nsCertType = server nsComment = "OpenSSL Generated Server Certificate" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer:always keyUsage = critical, digitalSignature, keyEncipherment extendedKeyUsage = serverAuth crlDistributionPoints = URI:http://pki.dominio.com/intermediate.crl [ ocsp ] # Extension for OCSP signing certificates (`man ocsp`). basicConstraints = CA:FALSE subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer keyUsage = critical, digitalSignature extendedKeyUsage = critical, OCSPSigning [ crl_ext ] # Extension for CRLs (`man x509v3_config`). authorityKeyIdentifier=keyid:always [ crl_info ] URI.0 = http://pki.dominio.com/sub-ca.crl URI.1 = https://www.dominio.com/pki/sub-ca.crl
希望实现类似Microsoft SubCA的效果:仅在生成CSR时指定SAN,签发时无需修改CA配置。
解决方案
要让OpenSSL子CA自动读取CSR中的SAN字段并写入签发的证书,只需修改子CA配置文件的两个核心设置:
1. 启用扩展字段复制
在[CA_default]段中添加以下配置:
copy_extensions = copy
该参数会让OpenSSL将CSR中包含的所有扩展字段(包括SAN)直接复制到最终签发的证书中,无需在CA配置里预先定义SAN值。
2. 确保server_cert扩展兼容
检查[server_cert]段,确保没有定义subjectAltName字段(如果已定义,会覆盖CSR中的值)。当前配置中的server_cert段未包含该字段,无需额外修改。
3. 重新签发证书
使用原有的签发命令重新生成证书即可:
openssl ca -config intermediate/sub-ca-openssl.cnf \ -extensions server_cert \ -days 375 -notext -md sha512 \ -in /root/ca/test3.psc.local.csr \ -out /root/ca/test3.psc.local.crt
4. 验证结果
执行以下命令确认证书中已包含SAN字段:
openssl x509 -noout -text -in test3.psc.local.crt | grep -A 3 "Subject Alternative Name"
注意事项
copy_extensions = copy会复制CSR中的所有扩展字段,需确保提交的CSR扩展合规,避免签发不符合安全要求的证书。若需更精细控制,可使用copy_extensions = copyall(但需谨慎,会复制所有扩展,包括可能的敏感字段)。- 确保子CA配置文件的权限正确(建议设置为
600,仅CA管理员可读写),避免配置被篡改。
内容的提问来源于stack exchange,提问作者Guille
相关产品推荐
相关产品推荐

