【问题标题】:Unable to `openssl verify' letsencrypt certificate无法“openssl 验证”letsencrypt 证书
【发布时间】:2018-11-21 00:35:24
【问题描述】:

我使用 Certbot 容器通过 Letsencrypt 生成证书:

$ mkdir /home/$USER/letsencrypt
$ docker run -it --rm -p 80:80 -p 443:443 -v /home/$USER/letsencrypt:/etc/letsencrypt certbot/certbot certonly --standalone --email user@example.com --agree-tos -d example.com

我导航到生成的证书:

$ cd /home/$USER/letsencrypt/live/example.com

我可以验证chain.pem

$ openssl verify chain.pem 
chain.pem: OK

我可以看到chain.pem 中的内容:

$ openssl x509 -noout -in chain.pem -subject -issuer
subject=C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
issuer=O = Digital Signature Trust Co., CN = DST Root CA X3

我无法验证cert.pem(大概是因为它需要链):

$ openssl verify cert.pem
CN = example.com
error 20 at 0 depth lookup: unable to get local issuer certificate
error cert.pem: verification failed

但我也无法验证fullchain.pem

$ openssl verify fullchain.pem
CN = example.com
error 20 at 0 depth lookup: unable to get local issuer certificate
error fullchain.pem: verification failed

证书似乎在浏览器中有效,但在 curl(和 Android http 客户端,这是真正的问题)中失败:

$ curl https://example.com
curl: (60) SSL certificate problem: unable to get local issuer certificate

我再次确认fullchain.pemcert.pemchain.pem 的串联。

所以:我不明白为什么fullchain.pem 不验证?

【问题讨论】:

  • 我可以在任何域的新生成的证书上重现这一点。如果我生成一个证书,cd.../live/example.com 并运行openssl verify fullchain.pem 我始终得到error 20 at 0 depth lookup: unable to get local issuer certificate / error fullchain.pem: verification failed
  • AIUI,openssl verify 只读取文件中的第一个证书,因此不能用于验证fullchain.pem

标签: ssl openssl lets-encrypt certbot


【解决方案1】:

我从man verify 中了解到这一点,阅读了untrusted 的描述。原来untrusted 实际上是您指定信任证书链的方式(当您这样说时似乎违反直觉)。

因此,您需要验证 Letsencrypt 证书的命令是:

openssl verify -untrusted chain.pem cert.pem

cert.pem 是您的证书,chain.pem 是 LE 中级证书。无需为此使用fullchain.pem

【讨论】:

  • 考虑使用-no-CApath 以避免使用系统通用信任库...然后使用-CAfile relevant-root-CA.crt(在您的情况下为DST Root CA X3
  • -untrusted 感觉不对,因为您想验证链,然后说允许不受信任的中间体。而是从这里获取正确的根 CA(注意:它可能不是 ISRG Root X1,而是下面提到的 TrustID X3 Root) ,然后执行openssl verify -CAfile <(cat root.pem chain.pem) cert.pem
【解决方案2】:

我在同一个问题上苦苦挣扎了 3 天。但该错误是由于我的 Apache 配置中的配置错误造成的。

我通过命令 openssl s_client -connect advertentiekracht.nl:443 发现返回:

Certificate chain
 0 s:/CN=advertentiekracht.nl
   i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3

包括“无法获得本地颁发者证书”

命令:[root@srv ssl]# openssl x509 -noout -in /etc/letsencrypt/live/advertentiekracht.nl/chain.pem -subject -issuer 显示丢失的链:

subject= /C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
issuer= /O=Digital Signature Trust Co./CN=DST Root CA X3

我当然不熟悉 openssl 和证书。肯定有很多原因导致“无法获得本地颁发者证书。但在你开始像我一样挖掘之前,请检查你的 http 服务器配置。对我来说那是 Apache。我有错别字定义 SSL 证书 hocus pocus 的位置。httpd 记录了下面的错误行

        SSLCertificateFile /etc/letsencrypt/live/advertentiekracht.nl/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/advertentiekracht.nl/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf

请注意第一行 SSLCertificateFile 应该是 SSLCertificateChainFile,我错过了对 cert.pem 和 chain.pem 的引用。下面的行解决了我的问题:

        SSLCertificateChainFile /etc/letsencrypt/live/advertentiekracht.nl/fullchain.pem
    SSLCertificateFile /etc/letsencrypt/live/advertentiekracht.nl/cert.pem
    SSLCertificateChainFile /etc/letsencrypt/live/advertentiekracht.nl/chain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/advertentiekracht.nl/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf

结果,一个完整的链条:

    Certificate chain
 0 s:/CN=advertentiekracht.nl
   i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
 1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
   i:/O=Digital Signature Trust Co./CN=DST Root CA X3

【讨论】:

    【解决方案3】:

    与直觉相反,我终于通过将根证书添加到链中来让 openssl verify 工作。感觉 Letsencrypt CA 应该已经可用了,所以我不相信这是正确的做法(并且欢迎 cmets)。

    步骤是:

    • Chrome 开发者工具 > 安全选项卡 > 查看证书 > 详细信息选项卡 > 选择根证书(“Builtin Object Token:DST Root CA X3”)
    • 点击导出,导出为 Base64-Encoded ASCII,单一证书(我将其命名为ca.pem

    将根连接到链中:

    $ ca.pem fullchain.pem > cachain.pem
    

    然后验证:

    $ openssl verify cachain.pem
    cachain.pem: OK
    

    这感觉“错误”,所以我想了解这是否是误报。

    【讨论】:

    • 这不就是验证根CA的有效性作为文件中的第一个条目吗?
    【解决方案4】:

    问题是 certbot 颁发的全链中的最后一个证书是由截至 2021 年 9 月 30 日的过期根证书(以 json 输出以说明链中的每个证书)颁发的证书 (https://letsencrypt.org/docs/dst-root-ca-x3-expiration-september-2021/)

    [
      {
        "subject": {
          "commonName": "..."
        },
        "issuer": {
          "countryName": "US",
          "organizationName": "Let's Encrypt",
          "commonName": "R3"
        },
        "version": 3,
        ...
        },
        "OCSP": [
          "http://r3.o.lencr.org"
        ],
        "caIssuers": [
          "http://r3.i.lencr.org/"
        ]
      },
      {
        "subject": {
          "countryName": "US",
          "organizationName": "Let's Encrypt",
          "commonName": "R3"
        },
        "issuer": {
          "countryName": "US",
          "organizationName": "Internet Security Research Group",
          "commonName": "ISRG Root X1"
        },
        "version": 3,
        "serialNumber": "912B084ACF0C18A753F6D62E25A75F5A",
        "notBefore": "Sep  4 00:00:00 2020 GMT",
        "notAfter": "Sep 15 16:00:00 2025 GMT",
        "caIssuers": [
          "http://x1.i.lencr.org/"
        ],
        "crlDistributionPoints": [
          "http://x1.c.lencr.org/"
        ]
      },
      {
        "subject": {
          "countryName": "US",
          "organizationName": "Internet Security Research Group",
          "commonName": "ISRG Root X1"
        },
        "issuer": {
          "organizationName": "Digital Signature Trust Co.",
          "commonName": "DST Root CA X3"
        },
        "version": 3,
        "serialNumber": "4001772137D4E942B8EE76AA3C640AB7",
        "notBefore": "Jan 20 19:14:03 2021 GMT",
        "notAfter": "Sep 30 18:14:03 2024 GMT",
        "caIssuers": [
          "http://apps.identrust.com/roots/dstrootcax3.p7c"
        ],
        "crlDistributionPoints": [
          "http://crl.identrust.com/DSTROOTCAX3CRL.crl"
        ]
      }
    ]
    

    请注意,链中的最后一项是由 DST Root CA X3 颁发的,如果您获取 http://apps.identrust.com/roots/dstrootcax3.p7c,您会看到它是新过期的 DST Root CA X3 证书。

    所以你得到

    $ openssl verify -CAfile fullchain.pem fullchain.pem
    server.pem: O = Digital Signature Trust Co., CN = DST Root CA X3
    error 10 at 1 depth lookup:certificate has expired
    O = Digital Signature Trust Co., CN = DST Root CA X3
    error 10 at 3 depth lookup:certificate has expired
    OK
    

    但是如果你从 fullchain.pem 中剥离最后一个证书并将输出放在 chain.pem 中

    $ openssl verify -CAfile chain.pem fullchain.pem
    server.pem: OK
    

    (请注意,verify 只检查 fullchain.pem 中的第一个证书)

    对于最新版本的 openssl,您可以使用 -partial_chain-trusted_first,但这些在 MacOS 上安装的 openssl 上不可用。

    我这里有几个 pem 处理工具:https://gitlab.com/Blockdaemon/pem2json

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-27
      • 2016-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多