使用 OpenSSL CLI 从 x509 证书获取链或 CA 颁发者



我正在尝试使用 OpenSSL 从证书构建链(或只是从某个地方获取它(,最好使用命令行界面。

我在互联网上找到了一些例子,但我被困在"我从哪里从证书中获取 CA 颁发者?

例如检查这个网站打开ssl命令备忘单,你会发现命令

OpenSSL s_client -showcerts -host example.com -port 443

来获取链。您可以使用www.google.com而不是example.com来尝试。 输出应该给你链。其他网站迟早使用相同的命令...

因此,我无法直接从证书中获取链,但我应该在某个地方询问链。

现在我的问题是:我在哪里获得主机名,我可以在哪里发送我的链请求?

我看了两张证书。

  1. stackexchange.com
  2. google.com

使用OpenSSL,我可以使用命令询问发行者

openssl x509 -in certFile -noout -issuer

和我分别得到

  1. 颁发者=C = US,O = 让我们加密,CN = 让我们加密授权 X3
  2. 发行人=C = 美国,O = 谷歌信托服务,CN = GTS CA 1O1

老实说,我不知道如何处理这些结果......

然后,使用命令进行调查

openssl x509 -text -in certFile

我找到了AIA扩展:

  1. CA Issuers - URI:http://cert.int-x3.letsencrypt.org/
  2. CA Issuers - URI:http://pki.goog/gsr2/GTS1O1.crt

好的,在第一个示例中,我终于可以使用该命令了

openssl s_client -showcerts -host http://cert.int-x3.letsencrypt.org/-port 443

但是对于谷歌,我不知道如何使用openssl下载链....我可以使用wget也许,但我没有从堆栈交换获得的相同格式......

所以,最后,我的问题:

  • 我应该如何处理这些差异?
  • 有没有更好的方法可以从证书中获取链,而无需询问 CA 颁发者?
  • CA发行人是AIA的扩展,我认为这不是强制性的,我可以依靠它吗?
  • 如何在不自己解析输出的情况下使用OpenSSL获取 CA 颁发者?(类似openssl x509 -caIssuer -in certFile(

PS:我最后要实现的是验证证书,遍历整个链,并检查链中每个证书的所有OCSP或CRL......如果您有C++的工作示例,或者只是使用 OpenSSL CLI,我将不胜感激:)

编辑:

我现在正在做的是自己创建链条。

使用 AIA 扩展,我获取 CA 颁发者 URI,下载 CA 颁发者证书(如果需要,转换为 PEM(,依此类推,直到我再也找不到 CA 颁发者。然后,它可能是一个根 CA。

之后,我手动收集所有 pem 并创建链。

知道这有点旧并且已经解决,但我想我会添加一个我编写的小脚本来解析 x509 输出中的 CA 颁发者:

getcaissuer() {
openssl x509 -noout -text -in $1 | awk '/^[ t]+CA Issuers[ t]+-[ t]+URI:/ { print gensub(/^.*URI:(.*)$/,"\1","g",$0); }'
}
# usage:  getcaissuer <certificate>

互联网上似乎有很多例子都考虑到了SSL证书。在SSL证书中,您只需连接到网站并下载完整的链即可。我认为在SSL协议本身中,服务器应该为您提供完整的链。

我正在为SMIME证书执行此操作,这就是我感到困惑的原因,因为我不能使用与SSL证书相同的方法。

在与我的同事交谈并将我正在做的事情与互联网上发现的一些类似程序进行比较后,AIA扩展似乎是正确的方法。也许它在 X509 标准中不是强制性的,但它似乎被广泛使用(我从未见过没有 AIA 扩展名的 SMIME 证书(。

然后,我手动创建链,使用 AIA 扩展名返回,直到找到没有此类扩展名的证书。

此时,这应该是一个根证书,我将尝试使用计算机中安装的证书对其进行验证。

(当然,不要忘记通过CRL或OCSP检查吊销状态(

到目前为止,一切都:)

根据@bng44270的回答,此脚本将沿着链条将证书抓取到当前目录

#!/bin/bash
# get-cert-chain.sh
machine=${1?No address passed}
machine_cert=${machine}.pem
# from https://stackoverflow.com/a/68637388/5401366
getcaissuer() {
openssl x509 -noout -text -in $1 -ext authorityInfoAccess | awk '/^[ t]+CA Issuers[ t]+-[ t]+URI:/ { print gensub(/^.*URI:(.*)$/,"\1","g",$0); }'
}
if [ ! -e "${machine_cert}" ];
then
openssl s_client -connect ${machine}:443 -showcerts </dev/null 2>/dev/null | openssl x509 -outform PEM >${machine_cert}
fi;
cur_cert=$machine_cert
while :;
do
# Get the first matching http line to grab the next cert loc
nextca=$(getcaissuer ${cur_cert} | grep -m1 http)
# ran out of stuff to retrieve
[ -z "${nextca}" ] && break
echo "Trying to get '${nextca}'"
nextfile=$(basename ${nextca})
if [ ! -e ${nextfile} ];
then
echo "Getting $nextca"
curl -sO $nextca
else
echo "Found ${nextfile}"
fi
# Convert
cat $nextfile | openssl x509 -inform DER -outform PEM > ${nextfile}.pem
# down the rabbit hole...
cur_cert=${nextfile}.pem
done

最新更新