windows - 如何使用OpenSSL/Curl检查双面安全的https连接

标签 windows ssl openssl authorization ssl-certificate

这个问题似乎之前被问过:
OpenSSL Verify return code: 20 (unable to get local issuer certificate)。但是,不同之处在于它与本地发行者证书有关。此外,答案不适用于Windows计算机。

问题描述
在Windows计算机上,我有一个试图与安全服务器联系的程序。双方都有证书。

问题:我无法联系它,所以我试图找出证书是否正确安装

搜索这里的堆栈溢出表明,即使我正在运行Windows计算机,找到问题的一个好方法就是为此使用OpenSsl。

作为检查是否正确安装了连接的所有证书的示例,建议我使用google.com检查连接:

openssl.exe s_client -connect google.com:443


(我的浏览器连接到该服务器没有问题)

响应的第一行是

CONNECTED(00000184)
depth=1 C = US, O = Google Trust Services, CN = Google Internet Authority G3
verify error:num=20:unable to get local issuer certificate
---
Certificate chain
 0 s:/C=US/ST=California/L=Mountain View/O=Google LLC/CN=*.google.com
   i:/C=US/O=Google Trust Services/CN=Google Internet Authority G3
 1 s:/C=US/O=Google Trust Services/CN=Google Internet Authority G3
   i:/OU=GlobalSign Root CA - R2/O=GlobalSign/CN=GlobalSign
---
Server certificate
-----BEGIN CERTIFICATE-----
...


并进一步降低两次相同的错误:

Verification error: unable to get local issuer certificate
Verify return code: 20 (unable to get local issuer certificate)


<OpenSSL documentation about s_client不能很好地说明这些错误。

那是什么意思呢?我是否缺少一些证书才能与google.com进行通信,或者我使用的程序不正确?

当然google.com只是一个例子。我选择了这个,所以我可以检查报告的问题是由于证书问题还是由于我使用的命令。

对于我尝试联系的实际服务器,我拥有作为.CER文件的适当证书(至根)。根证书位于winstore中。

最佳答案

帕特里克·梅夫策克(Patrick Mevzek)向我指出了正确的答案(谢谢帕特里克!)。由于需要进行一些调查,因此我决定将其写下来作为完整答案。

我正在Windows Server 2012中工作。较新的版本可能会以类似方式工作。要测试证书和通讯,我使用:


Windows的openssl。 Find a compiled version here
卷曲窗口here


档案:

所以我是服务器的客户端。有两种方式的安全认证:通过非常安全的方法,我们拥有以下文件:


可以信任的根证书:Root.Pem
根证书颁发的不信任证书链:A.PemB.PemC.Pem
私钥文件MyPrivate.keyC.Pem颁发的可信任证书,以确保我的身份:MyCertificate.pem


如果需要,将证书文件转换为PEM格式

如果证书不是PEM格式,我们需要先进行转换。要检查它们是否在PEM中,请在文本编辑器中将其打开。一个PEM文件如下所示:

-----BEGIN CERTIFICATE-----
MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO
...
-----END CERTIFICATE-----


如果不是,我们可以使用openSSL来转换文件:

openssl.exe x509 -inform DER -in myCertificate.cer -out myCertificate.Pem



通知:输入文件的格式:DER / NET / PEM(好吧,如果已经是PEM,则无需转换)
in / out:输入文件,输出文件


验证证书链

为了提高安全性,我分别验证了每个证书。一步执行此操作可能也很安全。


检查根证书的有效性。例如,通过使用已发布的指纹检查指纹。
检查不信任证书的有效性


(1)A.pem是否由Root.Pem发行?

openssl.exe verify -show_chain -CAfile root.pem A.pem


参数-CAfile包含受信任的证书。最后一个文件是包含要验证的证书的文件。

答复应类似于:

A.pem: OK
Chain:
depth=0: C = NL, ..., CN = <some text describing certificate A> (untrusted)
depth=1: C = NL, ..., CN = <some text describing the trusted root certificate>


(2)B.Pem是否由受信任的A.Pem发行?

现在A.pem是可信任的,我们可以检查B.Pem。为此,我们将中间证书A.Pem提到为this answer中所建议的不受信任

openssl.exe verify -show_chain -CAfile root.pem -untrusted A.pem B.pem


回复:

B.pem: OK
Chain:
depth=0: C = NL, ..., CN = <some text describing certificate B> (untrusted)
depth=1: C = NL, ..., CN = <some text describing certificate A> (untrusted)
depth=2: C = NL, ..., CN = <some text describing the trusted root certificate>


(3)我们可以信任其余证书链吗?

所以现在B可以信任了。要继续检查链,请将不受信任的CA文件串联到一个不受信任的.pem文件中。不要添加MyCertificate.Pem

-----BEGIN CERTIFICATE-----
MIIGNjCCBB6gAwIBA...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
jCCBB6gAwIBA34F..
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
dZBo31cAYsByRL...
-----END CERTIFICATE-----


和命令:

openssl.exe verify -show_chain -CAfile root.pem -untrusted untrusted.pem myCertificate.pem


回复:

MyCertificate.pem: OK
Chain:
depth=0: C = NL, ..., CN = <some text describing MyCertificate> (untrusted)
depth=1: C = NL, ..., CN = <some text describing certificate C> (untrusted)
depth=2: C = NL, ..., CN = <some text describing certificate B> (untrusted)
depth=3: C = NL, ..., CN = <some text describing certificate A> (untrusted)
depth=4: C = NL, ..., CN = <some text describing the trusted root certificate>


我想也许不需要所有这些中间步骤来检查有效性。

检查连接

现在证书链是受信任的,我们可以使用OpenSsl来检查连接。


使用文本编辑器或命令MyCertificate.pem将一个文件AllTrusted.pem中除Copy Root.Pem + A.Pem + B.Pem ... Trusted.Pem以外的所有证书串联在一起


命令:

openssl.exe s_client CAfile Trusted.Pem -connect google.nl:443


google.nl:443替换为正确的地址和端口

回覆,类似:

CONNECTED(00000124)
depth=1 C = US, O = Google Trust Services, CN = Google Internet Authority G3
verify error:num=20:unable to get local issuer certificate
---
Certificate chain
0 s:/C=US/ST=California/L=Mountain View/O=Google LLC/CN=google.com
  i:/C=US/O=Google Trust Services/CN=Google Internet Authority G3
1 s:/C=US/O=Google Trust Services/CN=Google Internet Authority G3
  i:/OU=GlobalSign Root CA - R2/O=GlobalSign/CN=GlobalSign
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIhWDCCIECgAwIBAgIQaEMB4EOx3++GhdWADJfgEjANBgkqhkiG9w0BAQsFADBU
...
-----END CERTIFICATE-----
subject=/C=US/ST=California/L=Mountain View/O=Google LLC/CN=google.com
issuer=/C=US/O=Google Trust Services/CN=Google Internet Authority G3


服务器发送了一个证书来标识自己。客户端应使用此证书及其受信任的CA链来检查服务器的身份。

为了继续进行通信,我们需要一个PEM文件,其中包含提到的发行者及其发行者,直到根为止。使用上述过程获取完整的证书链,然后将所有证书以正确的顺序添加到文件trusted.pem中。如果将接收到的证书复制粘贴到PEM文件(文本)中,则应该能够以与上述我验证MyCertificate.Pem相同的方式验证此接收到的证书。

安装了用于接收到的证书的CA证书后,我的openssl s_client命令回答为:

...
SSL handshake has read 8945 by
Verification: OK
---
New, TLSv1.2, Cipher is ...
Server public key is 2048 bit

Start Time: 1551779993
Timeout   : 7200 (sec)
Verify return code: 0 (ok)
Extended master secret: no


因此,用于识别服务器的证书链被接受。

标识我到服务器

下一步将检查我是否可以使用MyCertficate.pem在服务器上标识自己。

这是我第一次需要我的私钥文件。我们将为此使用curl:

命令:

curl.exe -v --cacert trusted.pem --cert MyCertificate.pem --key MyPrivate.key https://...



-v:详细
--cacert:文本文件,由信任的CA链串联到根,使用openssl verify验证
-证书:我用来证明自己身份的证书
--Key:此证书的私钥


回复:

...
* successfully set certificate verify locations:
*   CAfile: trustall.pem
...
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Request CERT (13):
* TLSv1.2 (IN), TLS handshake, Server finished (14):

* TLSv1.2 (OUT), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS handshake, CERT verify (15):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):

* TLSv1.2 (IN), TLS handshake, Finished (20):
...
* Server certificate:
*  subject: C=NL; ...
*  start date: Apr 19 12:10:31 2016 GMT
*  expire date: Apr 19 12:10:31 2019 GMT
...
*  issuer: C=NL; O= <description of certificate issuer; should be in trusted.pem>
*  SSL certificate verify ok.
> GET /exchange/ciot HTTP/1.1
> Host: ....
> User-Agent: curl/7.64.0
> Accept: */*
>
< HTTP/1.1 400 Bad Request


我们看到的:


TrustAll.Pem包含受信任的证书
(Out)客户端Hello-(In)Server Hello:显然我们是在说话
服务器发送证书并请求一个
客户发送其证书以标识自己
显示接收到的证书,服务器用来识别自己的证书。发行人应该是Trusted.pem
收到的证书将被验证并接受。数据传输可以开始
因为我没有发送任何数据,所以响应为400 Bad Request


这样就足以知道客户端和服务器都使用受信任的证书,并且可以进行通信

关于windows - 如何使用OpenSSL/Curl检查双面安全的https连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54923304/

相关文章:

c++ - 创建 CPU 使用率 >70% 的线程

ruby - 安装 openssl Ruby gem 失败,因为找不到 Ubuntu 中安装的 openssl

c# - ssl 或 https 在这种情况下什么最有用

c - 程序按预期工作,但打印结果后我收到错误消息

c++ - 为什么 Sleep() 会使后续代码减慢 40 毫秒?

node.js - 如何检查/获取 ssl 证书到期日期

ssl - 如何阻止未经授权的用户创建/删除kafka主题?

iOS https/主机没有 SSL 证书

Ruby OpenSSL,打印发行者和 pem 文件的主题

windows - xcopy语法? (批)