如何验证自签名根CA证书及通配符证书与服务器的匹配性?
-----END CERTIFICATE-----
- `*.custom.local`的通配符证书:
Bag Attributes
localKeyID: 01 00 00 00
friendlyName: Wildcard custom.local
...: ...
...: ...
subject=C = ..., ST = ..., L = ..., O = ..., OU = IT, CN = *.custom.local, emailAddress = ...
issuer=DC = local, DC = custom, CN = CUSTOM-ROOT-CA
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
- 该通配符证书对应的私钥:
-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
目前我通过以下方式验证三者组合: ```bash # 对比派生公钥,检查私钥是否属于通配符证书 [ "$(openssl x509 -pubkey -noout -in ./CUSTOM_WILDCARD.crt)" = "$(openssl rsa -pubout -outform PEM -in ./CUSTOM_WILDCARD.key 2>& /dev/null)" ] # 验证通配符证书信任链,确认其由根CA私钥签名 openssl verify -CAfile ./CUSTOM_ROOT_CA.crt ./CUSTOM_WILDCARD.crt
但该方式存在不足:未将证书/密钥与实际服务器验证。我想针对test.custom.local:443测试,该如何操作?
我尝试用openssl s_client命令连接,若返回码为0则认为本地证书密钥与服务器匹配:
echo | openssl s_client -connect test.custom.local:443 -CAfile ./CUSTOM_ROOT_CA.crt -cert ./CUSTOM_WILDCARD.crt -key ./CUSTOM_WILDCARD.key
初看有效,但修改密钥文件最后一个字符后,命令仍返回相同输出且退出码为0,说明该方法可能不安全,求正确验证方式。
为什么之前的方法无效?
openssl s_client的-cert和-key参数用于客户端证书认证——只有当服务器要求客户端出示证书时,这两个参数才会生效。你的场景是验证服务器使用的证书/私钥是否与本地文件匹配,这两个参数完全不相关,所以修改密钥后连接仍能成功。
方法1:对比服务器证书与本地通配符证书
先获取服务器当前使用的证书,再与本地证书对比:
# 获取服务器证书并保存到本地 openssl s_client -connect test.custom.local:443 -CAfile ./CUSTOM_ROOT_CA.crt < /dev/null | openssl x509 -out server_cert.crt # 对比证书的SHA256指纹(最直观) openssl x509 -noout -fingerprint -sha256 -in ./CUSTOM_WILDCARD.crt openssl x509 -noout -fingerprint -sha256 -in server_cert.crt
如果两个指纹完全一致,说明服务器使用的证书和你本地的通配符证书是同一个。
也可以直接对比证书内容(排除格式差异):
diff <(openssl x509 -in ./CUSTOM_WILDCARD.crt -outform PEM) <(openssl x509 -in server_cert.crt -outform PEM)
无输出说明内容完全一致。
方法2:验证服务器证书的信任链与域名匹配
确认服务器证书能被你的根CA信任,且域名符合通配规则:
openssl s_client -connect test.custom.local:443 -CAfile ./CUSTOM_ROOT_CA.crt < /dev/null | grep -E '(Verify return code|Subject:|Subject Alternative Name)'
正常输出应包含:
Verify return code: 0 (ok):说明证书链信任有效Subject: CN=*.custom.local:证书域名匹配- 若有SAN字段,应包含
DNS:*.custom.local或DNS:test.custom.local
方法3:验证服务器私钥与本地证书匹配(需服务器操作权限)
如果能访问服务器的私钥,可通过签名验证确认它与本地证书的公钥对应:
# 生成随机测试数据 openssl rand -out data.bin 1024 # 用服务器私钥签名数据(在服务器上执行) openssl dgst -sha256 -sign /path/to/server_private.key -out data.sig data.bin # 用本地证书的公钥验证签名(在本地执行) openssl dgst -sha256 -verify <(openssl x509 -pubkey -noout -in ./CUSTOM_WILDCARD.crt) -signature data.sig data.bin
返回Verified OK则说明服务器私钥与本地证书匹配。
内容的提问来源于stack exchange,提问作者Forivin

