使用openssl verify验证证书链

Ind*_*dra 111 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:无法获得本地颁发者证书

怎么了?

小智 138

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

试试这个:

openssl verify -CAfile RootCert.pem -untrusted Intermediate.pem UserCert.pem
Run Code Online (Sandbox Code Playgroud)

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

  • 在连接根和中间体之后,“-show_chain”选项被证明是有用的:“openssl verify -show_chain -CAfile inetmediates-and-root.pem UserCert.pem” (3认同)
  • 我正在对这个答案进行投票,因为我最近不得不这样做,在尝试了`man verify`列出的不同选项后,我发现`-untrusted`参数是指定中间证书时使用的正确参数. (2认同)
  • 我认为第二个答案:http://stackoverflow.com/a/31205833/173062 更准确 - 它将证书链传递给 -CAfile 参数。 (2认同)
  • `-untrusted`不检查证书链是否完全有效.请考虑将中间和root命令作为`-CAfile`传递给其他问题. (2认同)
  • 如果可能发生以下情况,请使用-untrusted for Intermediate.pem:https://mail.python.org/pipermail/cryptography-dev/2016-August/000676.html (2认同)
  • 这不是OP要求的,但如果你想验证NOT自签名链,那么使用系统/浏览器CA文件而不是你自己的.例如在OS X上使用openssl来自homebrew使用:`openssl verify -CAfile /usr/local/etc/openssl/cert.pem -untrusted Intermediate.pem UserCert.pem` (2认同)

Pet*_*ter 45

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

openssl verify -verbose -CAfile <(cat Intermediate.pem RootCert.pem) UserCert.pem
Run Code Online (Sandbox Code Playgroud)

更新:

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

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

不幸的是,当使用上面给出的推荐命令时,实际上是root/self-signed的"中间"证书 将被视为可信CA.

$ openssl verify -CAfile <(cat geotrust_global_ca.pem rogue_ca.pem)fake_sometechcompany_from_rogue_ca.com.pem fake_sometechcompany_from_rogue_ca.com.pem:OK

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

  • 警告:如果Intermediate.pem完全不受信任,请执行*NOT*.欲了解更多信息,请访问:https://mail.python.org/pipermail/cryptography-dev/2016-August/000676.html (7认同)

Tin*_*ino 13

问题是,这openssl -verify不起作用.

正如Priyadi所提到的那样,openssl -verify停在第一个自签名证书上,因此您并没有真正验证链,因为中间证书通常是自签名的.

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

请注意彼得的答案是正确的,但是输出结果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
Run Code Online (Sandbox Code Playgroud)

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

有一个GitHub要点可能有一些更新

此脚本的先决条件:

  • 您可以/etc/ssl/certs照常使用受信任的CA根数据,例如在Ubuntu上
  • 创建一个DIR存储3个文件的目录:
    • DIR/certificate.crt 其中包含证书
    • DIR/certificate.key 其中包含您的Web服务的密钥(没有密码)
    • 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的信息,请参阅如何将.crt转换为.pem并遵循黄砖路.

例:

你有:

  • intermediate2.crt 签署您的中级证书 certificate.crt
  • intermediate1.crt 烧伤的另一个中间证书 intermediate2.crt
  • crossigned.crt 这是来自另一个CA签署的交叉签名证书 intermediate1.crt
  • crossintermediate.crt这是签署的另一个CA的另一个中间件crossigned.crt(你可能永远不会看到这样的东西)

那么正确的cat看起来像这样:

cat intermediate2.crt intermediate1.crt crossigned.crt crossintermediate.crt > certificate.bundle
Run Code Online (Sandbox Code Playgroud)

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

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

  • "正如Priyadi所提到的,openssl -verify在第一个自签名证书上停止,因此您并不真正验证链,因为中间证书通常是自签名的." 显然中间证书永远不会自签名(如果它们是根证书).整个验证点是检查您是否已将链中的所有证书一直包含在受信任的根证书中.这正是openssl验证所做的.然而,openssl对其信任政策往往相当保守...... (6认同)
  • "通常中级证书是自签名的".这是错误的,这样的术语混淆使新手很难理解一个在正确的方式解释时实际上相当简单的话题.来自RFC 5280:"[...] CA证书可以进一步分为三类:交叉证书,自签发证书和自签名证书.交叉证书是CA证书,其中发行者和主题是不同的实体.交叉证书描述了两个CA之间的信任关系.[...]". (4认同)
  • 我是投票者之一。引发否决票的原因是:“您如何找出需要或不需要哪些文件以及按哪个顺序?好吧,进行实验,直到检查告诉您一切正常”。我不认为 SSL 是特例。像这样的问题应该有一个确定性的解决方案。 (3认同)
  • @ychaouche 谢谢!像你一样,我喜欢决定论的东西。问题是,“出了什么问题”以及如何使用“openssl verify”来做到这一点。当我们在 stackoverflow 上时,我解释了这一点,然后是一个程序化的(因此是确定性的)是/否答案。您甚至可以使用它在将新捆绑包安装到生产环境之前自动检查它。这完全回答了这个问题。你不喜欢的是我谈到了“如何创建合适的捆绑包?”的挫败感。因为我认为不能有一个简短的确定性答案,在这里的上下文中回答这个问题将是题外话。 (2认同)

Mar*_* An 12

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

openssl verify -no-CAfile -no-CApath -partial_chain -trusted Intermediate.pem UserCert.pem
Run Code Online (Sandbox Code Playgroud)

你会得到:

UserCert.pem: OK
Run Code Online (Sandbox Code Playgroud)

或者

UserCert.pem: verification failed
Run Code Online (Sandbox Code Playgroud)

2.同样的事情来验证发行人Intermediate.pemRootCert.pem

openssl verify -no-CAfile -no-CApath -partial_chain -trusted RootCert.pem Intermediate.pem
Run Code Online (Sandbox Code Playgroud)

如果上述两项验证均成功,则证书链已验证。


Mic*_*ael 6

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

  1. 从letsencrypt信任链下载root-cert和intermediate-cert:https://letsencrypt.org/certificates/
  2. 发出此命令:

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确保提出他的解决方案.

  • 嗯,看来约翰不喜欢我说谢谢。我坚持要强硬地说“谢谢”,所以这里是删除的文本:希望它对您的 LetsEncrypt 证书有所帮助。感谢 Priyadi,你的解决方案帮助我找到了这个命令。请务必支持他的解决方案。 (3认同)

Nic*_*her 5

openssl verify不以 SSL 客户端的方式处理证书链。您可以通过三步过程复制他们的操作:

(cat cert.pem chain.pem | diff -q fullchain.pem -) && \
openssl verify chain.pem && \
openssl verify -CAfile chain.pem cert.pem
Run Code Online (Sandbox Code Playgroud)

这将确认fullchain.pem== cert.pem+chain.pem并且根据您系统上安装的 CA(通常来自/etc/ssl/certs您的ca-certificates软件包)确认它是合法的。


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

  • cert.pem
  • chain.pem
  • fullchain.pem
  • privkey.pem

其中,您的证书对是 ( fullchain.pem, privkey.pem),而不是( cert.pem, privkey.pem) 也不是 ( chain.pem, privkey.pem)。

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

ssl_certificate /etc/letsencrypt/domain.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/domain.example.com/privkey.pem;
Run Code Online (Sandbox Code Playgroud)