使用openssl verify验证证书链

时间:2014-08-25 08:51:15

标签: openssl certificate

我正在建立一个拥有以下组件的自己的证书链:
Root Certificate - Intermediate Certificate - User Certificate
Root Cert是自签名证书,中级证书由Root和User by Intermediate签名。

现在我想验证用户证书是否有根证书的锚点。


openssl verify -verbose -CAfile RootCert.pem Intermediate.pem
验证没问题。在下一步中,我使用
验证用户证书 openssl verify -verbose -CAfile Intermediate.pem UserCert.pem
并且验证在0深度查找时显示错误20:无法获得本地颁发者证书

有什么问题?

8 个答案:

答案 0 :(得分:117)

来自'verify'文档:“如果找到的证书是其自己的颁发者,则认为它是根CA”。换句话说,根CA需要自签名才能进行验证。这就是你的第二个命令不起作用的原因。

请改为尝试:

openssl verify -CAfile RootCert.pem -untrusted Intermediate.pem UserCert.pem

它将在一个命令中验证您的整个链。

答案 1 :(得分:39)

这是cat为数不多的合法工作之一:

openssl verify -verbose -CAfile <(cat Intermediate.pem RootCert.pem) UserCert.pem

更新

正如Greg Smethells在评论中指出的那样,这个命令隐含地信任Intermediate.pem 。我建议阅读the post Greg references的第一部分(第二部分是关于pyOpenSSL的,与此问题无关)。

如果帖子消失,我会引用重要段落:

  

不幸的是,“中间”证书实际上是root / self-signed   使用建议的命令时,将被视为受信任的CA   以上:

     

$ openssl verify -CAfile&lt;(cat geotrust_global_ca.pem rogue_ca.pem)   fake_sometechcompany_from_rogue_ca.com.pem   fake_sometechcompany_from_rogue_ca.com.pem:好的

似乎openssl将在遇到根证书时立即停止验证链,如果它是自签名的,也可能是Intermediate.pem。在这种情况下,不考虑RootCert.pem。因此,在依赖上述命令之前,请确保Intermediate.pem来自受信任的来源。

答案 2 :(得分:12)

问题是,openssl -verify没有完成这项工作。

As Priyadi mentionedopenssl -verify在第一个自签名证书处停止,因此您并未真正验证链,因为中间证书通常是自签名的。

  

我认为您希望101%确定,在尝试将其安装到高效的Web服务中之前,证书文件是正确的。这个配方在这里执行这个飞行前检查。

请注意the answer of Peter is correct,但是openssl -verify的输出并不是所有真正后续工作的线索。是的,它可能会发现一些问题,但并非全部。

这是一个脚本,用于在将证书链安装到Apache之前验证证书链。也许这可以通过一些更神秘的OpenSSL魔法来增强,但我不是OpenSSL大师和以下作品:

#!/bin/bash
# This Works is placed under the terms of the Copyright Less License,
# see file COPYRIGHT.CLL.  USE AT OWN RISK, ABSOLUTELY NO WARRANTY. 
#
# COPYRIGHT.CLL can be found at http://permalink.de/tino/cll
# (CLL is CC0 as long as not covered by any Copyright)

OOPS() { echo "OOPS: $*" >&2; exit 23; }

PID=
kick() { [ -n "$PID" ] && kill "$PID" && sleep .2; PID=; }
trap 'kick' 0

serve()
{
kick
PID=
openssl s_server -key "$KEY" -cert "$CRT" "$@" -www &
PID=$!
sleep .5    # give it time to startup
}

check()
{
while read -r line
do
    case "$line" in
    'Verify return code: 0 (ok)')   return 0;;
    'Verify return code: '*)    return 1;;
#   *)  echo "::: $line :::";;
    esac
done < <(echo | openssl s_client -verify 8 -CApath /etc/ssl/certs/)
OOPS "Something failed, verification output not found!"
return 2
}

ARG="${1%.}"
KEY="$ARG.key"
CRT="$ARG.crt"
BND="$ARG.bundle"

for a in "$KEY" "$CRT" "$BND"
do
    [ -s "$a" ] || OOPS "missing $a"
done

serve
check && echo "!!! =========> CA-Bundle is not needed! <========"
echo
serve -CAfile "$BND"
check
ret=$?
kick

echo
case $ret in
0)  echo "EVERYTHING OK"
    echo "SSLCertificateKeyFile $KEY"
    echo "SSLCertificateFile    $CRT"
    echo "SSLCACertificateFile  $BND"
    ;;
*)  echo "!!! =========> something is wrong, verification failed! <======== ($ret)";;
esac

exit $ret
  

请注意,EVERYTHING OK之后的输出是Apache设置,因为使用NginXhaproxy的人通常也可以完美地阅读和理解这一点;)

有一个GitHub Gist可能会有一些更新

此脚本的先决条件:

  • 您可以像往常一样在/etc/ssl/certs中拥有受信任的CA根数据,例如在Ubuntu上
  • 创建一个存储3个文件的目录DIR
    • DIR/certificate.crt包含证书
    • DIR/certificate.key,其中包含您的网络服务的密钥(不含密码)
    • DIR/certificate.bundle,其中包含CA-Bundle。关于如何准备捆绑包,请参阅下文。
  • 现在运行脚本:./check DIR/certificate(这假定脚本在当前目录中名为check
  • 脚本输出CA-Bundle is not needed的可能性非常小。这意味着,您(阅读:/etc/ssl/certs/)已经信任签名证书。但这在WWW中是不太可能的。
  • 对于此测试,工作站上的端口4433必须未使用。最好只在安全的环境中运行它,因为它很快向公众开放端口4433,这可能会在恶劣的环境中看到外部连接。

如何创建certificate.bundle文件?

在WWW中,信任链通常如下所示:

  • 来自/etc/ssl/certs的可信证书
  • 未知的中间证书,可能由另一个CA签署
  • 您的证书(certificate.crt

现在,评估从下到上进行,这意味着,首先,您的证书被读取,然后需要未知的中间证书,然后可能会签署交叉签名证书,然后查询/etc/ssl/certs找到合适的可信证书。

ca-bundle必须以正确的处理顺序组成,这意味着,第一个需要的证书(签署证书的中间证书)首先出现在捆绑中。然后需要交叉签名证书。

通常,您的CA(签署证书的机构)将提供此类正确的ca-bundle文件。如果没有,您需要选择所有需要的中间证书并将它们cat一起放入一个文件中(在Unix上)。在Windows上,您只需打开一个文本编辑器(如notepad.exe)并将证书粘贴到文件中,第一个需要在顶部,然后跟随其他文件。

还有另外一件事。文件需要采用PEM格式。一些CA发布DER(二进制)格式。 PEM很容易发现:它是ASCII可读的。有关如何将某些内容转换为PEM的信息,请参阅How to convert .crt to .pem并按照黄砖路行驶。

示例:

你有:

  • intermediate2.crt签署了您的certificate.crt
  • 的中间证书
  • intermediate1.crt另一个中间证书,其中包含intermediate2.crt
  • crossigned.crt这是来自另一个CA的交叉签名证书,签名为intermediate1.crt
  • crossintermediate.crt这是签署crossigned.crt的其他CA的另一个中间人(您可能永远不会看到这样的事情)

然后正确的cat将如下所示:

cat intermediate2.crt intermediate1.crt crossigned.crt crossintermediate.crt > certificate.bundle

你怎么能找出需要的文件和顺序?

好吧,试验,直到check告诉你一切正常。它就像一个解决谜语的电脑益智游戏。每一个。单。时间。即使是专业人士。但是每次你需要这样做时你会变得更好。所以你绝对不会因为那种痛苦而独自一人。它是SSL,你是&#39;知道? SSL可能是我在30多年的专业系统管理中见过的最糟糕的设计之一。有没有想过为什么加密在过去30年里还没有成为主流?这就是原因。 &#39;努夫说。

答案 3 :(得分:5)

我必须对letsencrypt证书进行验证,我这样做了:

  1. 从letsencrypt信任链中下载root-cert和intermediate-cert:https://letsencrypt.org/certificates/
  2. 发出此命令:
  3. openssl verify -CAfile letsencrypt-root-cert/isrgrootx1.pem.txt -untrusted letsencrypt-intermediate-cert/letsencryptauthorityx3.pem.txt /etc/letsencrypt/live/sitename.tld/cert.pem /etc/letsencrypt/live/sitename.tld/cert.pem: OK

    希望它可以帮助您获得letsencrypt证书。 感谢Priyadi,您的解决方案帮助我找到了这个命令。 Palease确保提出他的解决方案。

答案 4 :(得分:3)

在完全相同的问题上打了一整天之后,在没有SSL证书的先验知识的情况下,我下载了CERTivity Keystores Manager并将我的密钥库导入其中,并获得了明确的证书链可视化。< / p>

屏幕截图:

enter image description here

答案 5 :(得分:3)

如果您只想验证UserCert.pem 发布者实际上 Intermediate.pem,请执行以下操作(示例使用:OpenSSL 1.1.1 ):

openssl verify -no-CAfile -no-CApath -partial_chain -trusted Intermediate.pem UserCert.pem

您将获得:

UserCert.pem: OK

UserCert.pem: verification failed

答案 6 :(得分:0)

openssl verify 不像 SSL 客户端那样处理证书链。您可以通过三步流程复制他们所做的事情:

(cat cert.pem chain.pem | diff -q fullchain.pem -) && \
openssl verify chain.pem && \
openssl verify -CAfile chain.pem cert.pem

这将确认 fullchain.pem == cert.pem + chain.pem 并且根据您系统上安装的 CA(通常在 /etc/ssl/certs 中),它是合法的1}} 包)。


如果您尝试验证letsencrypt/ACME,请注意letsencrypt为每个域提供四个文件:

  • ca-certificates
  • cert.pem
  • chain.pem
  • fullchain.pem

其中,您的证书对是 (privkey.pem, fullchain.pem), not (privkey.pem, cert.pem) 或 ({{1 }}, privkey.pem).

例如,在 nginx.conf 中,您将输入:

chain.pem

答案 7 :(得分:-5)

您可以使用openssl轻松验证证书链。 fullchain将包含CA证书,因此您应该看到有关CA和证书本身的详细信息。

openssl x509 -in fullchain.pem -text -noout