使用链接的CA和链接的证书进行OpenSSL验证 [英] Openssl verify with chained CA and chained Cert

查看:406
本文介绍了使用链接的CA和链接的证书进行OpenSSL验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的证书链如下: root CA -> intermediate CA -> org CA -> client Cert

当我验证CA为root CA -> intermediate CA -> org CA的客户端证书时,它起作用:

$ cat org_1_ca/ca_crt.pem intermediate_ca/ca_crt.pem root_ca/ca_crt.pem > /tmp/test123.pem $ openssl verify -CAfile /tmp/test123.pem client/client_crt.pem client_crt.pem: OK

但是,当我将客户证书与组织CA(org CA -> client Cert)链接在一起,并将其余链作为CA(root CA -> intermediate CA)时,它却没有:

$ cat intermediate_ca/ca_crt.pem root_ca/ca_crt.pem > /tmp/test12.pem $ openssl verify -CAfile /tmp/test12.pem client/org1_client_crt.pem client/org1_client_crt.pem: C = US, ST = CA, L = LA, O = PP, OU = TEST, CN = user error 20 at 0 depth lookup:unable to get local issuer certificate

这根本上是错误的还是openssl verify不喜欢吗?我用nginx和openssl connect尝试了同样的事情,那里没有运气.感谢您的帮助.

解决方案

openssl命令行verify操作从作为操作数给出的文件中仅读取一个证书,第一个证书如果给出多个文件,则从每个文件中获取.这与用-CAfile -trusted -untrusted选项指定的文件不同,该文件可以(通常确实)包含多个证书.

您的文件client/org1_client_crt.pem大概按此顺序包含客户端证书和组织CA"证书.仅使用客户端证书,而忽略组织CA"证书,因此您没有有效的链来进行验证.

如果您想使用命令行来模仿/测试接收方(对于客户端证书,服务器)将进行的验证,请提供叶子证书作为操作数,并为所有其他传输的(链式)证书提供-untrusted,以及信任库中的锚点以及任何已知"中间体,无论是显式的还是默认的.

没有openssl connect操作;我认为您的意思是openssl s_client,其中包括-connect的选项,因为那是一个使用客户端证书链的地方. s_client-cert选项类似地仅使用文件中的第一个证书.除了最新版本1.1.0以外,命令行上没有用于指定客户端链的选项,即使没有文档也没有记录,因此尽管API/库很长,但您仍必须仔细阅读帮助消息或代码.支持此功能,用于编写自己的代码.

如果要通过服务器将完整链的客户端证书发送到服务器(按照RFC的规定),请通过1.0.2,假定服务器请求的客户端身份验证不是通常的,也不是nginx的默认身份验证(除其他外) ,您必须使用技巧:在 truststore 中提供客户端链所需的所有证书,以及验证服务器所需的锚点,或者明确地使用-CAfile和/或-CApath,或者使用(如果需要,可以修改)默认信任库,除非您的openssl是较旧的非RedHat版本,其中默认信任库仅在s_client s_server s_time中不起作用.

s_server中的服务器证书/链也是如此,只是它几乎总是使用而不是很少使用.

I have a certificate chain as: root CA -> intermediate CA -> org CA -> client Cert

When I verify the client cert with CA as root CA -> intermediate CA -> org CA, it works:

$ cat org_1_ca/ca_crt.pem intermediate_ca/ca_crt.pem root_ca/ca_crt.pem > /tmp/test123.pem $ openssl verify -CAfile /tmp/test123.pem client/client_crt.pem client_crt.pem: OK

But when I chained my client cert with org CA (org CA -> client Cert), and have the rest of the chain as CA (root CA -> intermediate CA), it doesn't:

$ cat intermediate_ca/ca_crt.pem root_ca/ca_crt.pem > /tmp/test12.pem $ openssl verify -CAfile /tmp/test12.pem client/org1_client_crt.pem client/org1_client_crt.pem: C = US, ST = CA, L = LA, O = PP, OU = TEST, CN = user error 20 at 0 depth lookup:unable to get local issuer certificate

Is this something that fundamentally wrong or openssl verify doesn't like that? I tried the same thing with nginx and and openssl connect and there was no luck there. Any help is appreciated.

解决方案

The openssl commandline verify operation reads only one certificate, the first one, from the file given as operand, or from each file if more than one is given. This differs from the files specified with the -CAfile -trusted -untrusted options which can (and typically do) contain multiple certs.

Your file client/org1_client_crt.pem presumably contains the client cert and the 'org CA' cert, in that order. Only the client cert is used, the 'org CA' cert is ignored, and as a result you do not have a valid chain to verify.

If you want to use commandline to mimic/test the validation that a receiver (for a client cert, the server) would do, supply the leaf cert as the operand and all other transmitted (chain) certs with -untrusted, and the anchor(s) plus any 'known' intermediates in the truststore either explicit or defaulted.

There is no openssl connect operation; I assume you mean openssl s_client with options including -connect since that's one place it would make sense to use a client cert chain. The -cert option to s_client similarly uses only the first cert in the file. There is no option on commandline to specify the client chain except in the most recent version, 1.1.0, and even there it isn't documented so you have to read the help message carefully or the code, although the API/library has long supported this for code you write yourself.

Through 1.0.2 if you want to send a client cert with full chain to the server (as you should per the RFCs), assuming the server requests client authentication which is not usual and not the default for nginx (among others), you have to use a trick: supply all the certs needed for the client chain in the truststore, in addition to the anchor(s) needed to verify the server, either using -CAfile and/or -CApath explicitly, or using (modifying if needed) the default truststore unless your openssl is an older non-RedHat version where the default truststore didn't work in s_client s_server s_time only.

And the same is true about the server cert/chain in s_server except that it is used almost always instead of very rarely.

这篇关于使用链接的CA和链接的证书进行OpenSSL验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆