curl openssl 无法验证 IIS 7 自签名证书,即使添加到 curl-ca-bundle.crt 也是如此。



我在Windows Server Enterprise 2008上使用IIS 7生成了一个用于IIS的自签名证书(基本上是单击按钮)。

然而,即使我导出并将此证书添加到windows客户端的curl-ca-bundle.crt中,它和openssl.exe都不会正确验证证书:

openssl s_client -CAfile curl-ca-bundle.crt -showcerts -connect myserver.ad.pri:443
CONNECTED(00000003)
depth=0 /CN=myserver.ad.pri
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 /CN=myserver.ad.pri
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
 0 s:/CN=myserver.ad.pri
   i:/CN=myserver.ad.pri
-----BEGIN CERTIFICATE-----
MIIDADCCAeigAwIBAgIQTi9gdBLdo6pJ1h4Zljr/wzANBgkqhkiG9w0BAQUFADAp
....
-----END CERTIFICATE-----
---
Server certificate
subject=/CN=myserver.ad.pri
issuer=/CN=myserver.ad.pri
---
No client certificate CA names sent
---
SSL handshake has read 924 bytes and written 444 bytes
---
New, TLSv1/SSLv3, Cipher is AES128-SHA
Server public key is 2048 bit
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : AES128-SHA
    Session-ID: 
    Session-ID-ctx:
    Master-Key: 
    Key-Arg   : None
    Start Time: 1377728216
    Timeout   : 300 (sec)
    Verify return code: 21 (unable to verify the first certificate)
---
read:errno=104

我使用IE将证书导出到Base-64 Encoded,它是openssl可读的PEM:openssl x509-通知PEM-在myserver.crt中-文本

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            4e:2f:60:74:12:dd:a3:aa:49:d6:1e:19:96:3a:ff:c3
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: CN=myserver.ad.pri
        Validity
            Not Before: Aug 26 15:38:46 2013 GMT
            Not After : Aug 26 00:00:00 2014 GMT
        Subject: CN=myserver.ad.pri
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (2048 bit)
                Modulus (2048 bit):
                    ....
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage:
                Key Encipherment, Data Encipherment
            X509v3 Extended Key Usage:
                TLS Web Server Authentication
    Signature Algorithm: sha1WithRSAEncryption
        ...
-----BEGIN CERTIFICATE-----
....

使用相同curl-ca-bundle.crt的openssl/ccurl将验证来自google.com:443等的证书。

当我无法让NodeJS HTTP客户端连接到带有自签名证书的IIS实例(通过IIS管理器创建的证书)时,我也遇到了这种情况(我很惊讶更多的人没有遇到这种情况。)!

这似乎是因为IISManager为此目的创建的证书指定了一些"密钥用法"扩展密钥加密"one_answers"数据加密"。

事实证明,当openssl遇到指定"密钥用法"的证书,但未能指定"certSign"用法时,即使该证书已正确提供给openssl代码,openssl代码也会将其视为可能的CA证书(这意味着它无法根据所述不存在的CA验证证书!)。

(请参阅此处的逻辑https://github.com/openssl/openssl/blob/6f0ac0e2f27d9240516edb9a23b7863e7ad02898/crypto/x509v3/v3_purp.c#L503)

解决方案如上所述,即使用正确的密钥用法(或无密钥用法扩展!)创建自己的证书

我还认为我应该包括一种创建自签名证书的替代方法,如果你在windows平台上,openssl客户端会很满意。

首先从这里下载powershell脚本

在powershell控制台(管理)中,从包含下载脚本的文件夹中执行以下命令

New-SelfsignedCertificateEx -StoreLocation "LocalMachine" -KeyUsage "DigitalSignature,KeyEncipherment,KeyCertSign" -Subject "CN=<HOST_NAME_TO_USE>" -FriendlyName "<HOST_NAME_TO_USE>" -SignatureAlgorithm sha256 -SubjectAlternativeName "<HOST_NAME_TO_USE>","anotherhost.org","someotherdomain.com"

执行上述命令后,LocalMachine\Personal Certificates存储将包含一个自签名证书,IIS可以使用该证书进行SSL通信。(请注意,您可能还需要将此证书复制到一个受信任的根存储中,以确保该证书在该机器上是受信任的)

我通过使用openssl创建一个自签名的CA证书来解决这个问题,然后创建一个服务器证书请求(也在openssl中,由于某种原因,openssl不喜欢对IIS生成的请求进行签名),用以前的CA证书对其进行签名,然后导出到PKCS12。然后导入IIS。一旦CA证书添加到curl-CA-bundle.crt,它将正确验证链:

生成CA:

openssl req -new -x509 -days 3650 -extensions v3_ca 
-keyout cakey.pem -out cacert.pem -config /etc/ssl/openssl.cnf 
-newkey rsa:2048

生成服务器密钥和签名请求:

openssl req -new -nodes -out server-csr.pem -keyout server-key.pem -newkey rsa:2048

用CA:签署请求

openssl ca -config /etc/ssl/openssl.cnf -cert cacert.pem -keyfile cakey.pem 
-out server-cert.pem -in server-csr.pem

将服务器证书导出到PKCS#12:

openssl pkcs12 -export -out server-key-cert.pfx 
-inkey server-key.pem -in server-cert.pem -certfile cacert.pem

将server-key-cert.pfx导入IIS。(重新)将站点绑定的SSL绑定绑定到证书。

将cacert.pem附加到客户端的curl-ca-bundle.crt。openssl s_client-showcerts-CAfile curl-ca-bandle.crt-connect server:443具有深度0和1,并将验证返回。

注意:请确保在openssl.cn中的[usr_cert]部分下启用了keyUsage=nonRepudiation、digitalSignature、keyEncipherment,否则请求将不包含这些keyUsage,IIS将对绑定进行投诉。

最新更新