错误信息
verify error:num=21:unable to verify the first certificate
也可能输出为
- Verify return code: 21 (unable to verify the first certificate)
openssl s_client 输出为“verify error:num=21:…”和“Verify return code: 21 (…)”。Node.js 把同样的情况报告为 UNABLE_TO_VERIFY_LEAF_SIGNATURE(“unable to verify the first certificate”)。
OpenSSL CLI (openssl s_client) — X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE
含义
OpenSSL 错误 21(X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE):证书链中只有一张证书,即服务器自己的证书,而且找不到它的颁发者,因此连叶子证书的签名都无法检查。s_client 通常会紧接在它之前针对深度 0 输出错误 20。解决办法几乎总在服务器一侧:服务器必须发送自己的中间证书。
原因
服务器只配置了叶子证书
常见用了 cert.pem 而不是 fullchain.pem、粘贴到负载均衡器中的证书没有附带证书链,或者导入 Java 密钥库的条目没有包含签发它的 CA。
配置了证书链,但没有发送
偶见有些服务器要求在单独的指令或字段中配置证书链(旧版 Apache 的 SSLCertificateChainFile、云负载均衡器的证书链输入框);放错位置的证书包会被静默忽略。
服务器发送的中间证书并没有签发这张叶子证书
偶见CA 更换中间证书后,旧的证书链文件发送的证书不是叶子证书的颁发者;OpenSSL 因此无法使用它。
修复方法
- 1.
检查服务器发送的内容
如果只有一张证书,且其颁发者(i:)是中间 CA,就可以确认是这个问题。
bash openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts </dev/null 2>/dev/null \ | grep -E '^ *[0-9]+ s:|^ *i:' - 2.
提供叶子证书 + 中间证书
按顺序拼接叶子证书和签发它的中间证书,并在服务器上配置这个文件;输出证书包的内容以检查顺序。
bash # Build the file the server should use: leaf, then intermediates (issuer of each previous one) cat server.pem intermediate.pem > fullchain.pem openssl crl2pkcs7 -nocrl -certfile fullchain.pem | openssl pkcs7 -print_certs -noout # check the order - 3.
找到正确的中间证书
叶子证书的颁发机构信息访问(Authority Information Access)扩展给出了其颁发者证书的 URL;下载该证书,必要时转换为 PEM,再把它添加到证书链文件中。
bash # Where to download the missing intermediate: the leaf's Authority Information Access URL openssl x509 -in server.pem -noout -ext authorityInfoAccess curl -sS -o intermediate.der http://ca.example.com/issuing-ca.crt openssl x509 -inform der -in intermediate.der -out intermediate.pem