【问题标题】:openssl s_client -cert: Proving a client certificate was sent to the serveropenssl s_client -cert:证明客户端证书已发送到服务器
【发布时间】:2013-06-16 17:09:34
【问题描述】:

背景

我陷入了与服务提供商的相互指责中,该服务提供商的 API 受 SSL 服务器和客户端证书保护。

  • 我已生成 CSR,从公共 CA(本例中为 GoDaddy)获得证书,并将证书和 CA 链提供给服务提供商。
  • 据说他们已将 CA 和我的客户端证书加载到他们的网关中。
  • 我正在使用openssl s_client -connect ... -cert ... -key ... 进行最基本的级别测试
  • 提供商告诉我,他们的日志表明我的请求根本不包括客户端 SSL 证书。
  • 奇怪的是,我的证书的正确 CA 颁发者确实出现在 SSL 握手期间提供的“可接受的客户端证书 CA 名称”列表中。
  • 作为参考,我创建并提供给他们进行测试的自签名证书实际上可以正常工作。

一个示例(失败)请求

[shell ~]$ openssl s_client -connect host:443 -cert cert_and_key.pem -key cert_and_key.pem -state -quiet
CONNECTED(00000003)
SSL_connect:before/connect initialization
SSL_connect:SSLv2/v3 write client hello A
SSL_connect:SSLv3 read server hello A
depth=2 **SNIP**
verify return:1
depth=1 **SNIP**
verify return:1
depth=0 **SNIP**
verify return:1
SSL_connect:SSLv3 read server certificate A
SSL_connect:SSLv3 read server key exchange A
SSL_connect:SSLv3 read server certificate request A
SSL_connect:SSLv3 read server done A
SSL_connect:SSLv3 write client certificate A
SSL_connect:SSLv3 write client key exchange A
SSL_connect:SSLv3 write certificate verify A
SSL_connect:SSLv3 write change cipher spec A
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
SSL3 alert read:fatal:unknown CA
SSL_connect:failed in SSLv3 read finished A
140011313276744:error:14094418:SSL routines:SSL3_READ_BYTES:tlsv1 alert unknown ca:s3_pkt.c:1197:SSL alert number 48
140011313276744:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:184:

我对@9​​87654323@ 错误的解读是服务器无法识别我(实际上)提供的证书的颁发者。但是,提供商“向我保证”CA 证书已正确加载,否则我无法说服他们。

问题

所以,抛开其他(广泛的)故障排除步骤,我真正想知道的是:

openssl s_client 是否有一些可用输出最终表明客户端证书不仅是服务器请求的,而且实际上是在 SSL 握手期间传输到服务器的?

我尝试过-state-msg-debug-trace 选项,但没有解释输出所需的背景知识。

EJP 的回答表明,我提供的示例输出足以证明 write client certificate A,但无论是否在命令行上使用了 -cert 选项,此输出都会出现,因此它并不表示证书是已发送

【问题讨论】:

    标签: ssl openssl ssl-certificate


    【解决方案1】:

    为了验证客户端证书正在发送到服务器,您需要分析 -state-debug 标志组合的输出。

    首先作为基线,尝试运行

    $ openssl s_client -connect host:443 -state -debug
    

    您将获得大量输出,但我们感兴趣的行如下所示:

    SSL_connect:SSLv3 read server done A
    write to 0x211efb0 [0x21ced50] (12 bytes => 12 (0xC))
    0000 - 16 03 01 00 07 0b 00 00-03                        .........
    000c - <SPACES/NULS>
    SSL_connect:SSLv3 write client certificate A
    

    这里发生了什么:

    • -state 标志负责显示上一节的结尾:

      SSL_connect:SSLv3 read server done A  
      

      这仅对帮助您在输出中找到自己的位置很重要。

    • 然后-debug 标志显示在下一步中发送的原始字节:

      write to 0x211efb0 [0x21ced50] (12 bytes => 12 (0xC))
      0000 - 16 03 01 00 07 0b 00 00-03                        .........
      000c - <SPACES/NULS>
      
    • 最后,-state 标志再次报告了-debug 刚刚回显的步骤的结果:

      SSL_connect:SSLv3 write client certificate A
      

    换句话说:s_client 完成读取从服务器发送的数据,并将 12 个字节作为(我假设是)“无客户端证书”消息发送到服务器。。 p>


    如果您重复测试,但这次包括 -cert-key 标志,如下所示:

    $ openssl s_client -connect host:443 \
       -cert cert_and_key.pem \
       -key cert_and_key.pem  \
       -state -debug
    

    “read server done” 行和 “write client certificate” 行之间的输出会更长,代表您的客户端证书的二进制形式:

    SSL_connect:SSLv3 read server done A
    write to 0x7bd970 [0x86d890] (1576 bytes => 1576 (0x628))
    0000 - 16 03 01 06 23 0b 00 06-1f 00 06 1c 00 06 19 31   ....#..........1
    (*SNIP*)
    0620 - 95 ca 5e f4 2f 6c 43 11-                          ..^%/lC.
    SSL_connect:SSLv3 write client certificate A
    

    1576 bytes 本身就是一个很好的指示,表明证书已被传输,但最重要的是,右侧列将显示证书中人类可读的部分:您应该能够识别证书的 CN 和颁发者字符串。

    【讨论】:

      【解决方案2】:

      我知道这是一个老问题,但似乎还没有答案。 我已经复制了这种情况,但我正在编写服务器应用程序,所以我也能够确定服务器端发生了什么。当服务器要求它并且它在 s_client 命令行中有对真实证书的引用时,客户端会发送证书。我的服务器应用程序设置为请求客户端证书,如果没有提供则失败。这是我发出的命令行:

      Yourhostname here -vvvvvvvvvv s_client -connect <hostname>:443 -cert client.pem -key cckey.pem -CAfile rootcert.pem -cipher ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH -tls1 -state

      当我省略命令的“-cert client.pem”部分时,服务器端握手失败,s_client 命令失败并报告错误。我仍然收到报告“未发送客户端证书 CA 名称”,但我认为上面已经回答了这个问题。

      那么简短的回答是,服务器确定客户端在正常操作条件下是否会发送证书(s_client 不正常),失败是由于服务器无法识别所提供证书中的 CA。尽管我的项目需要双向身份验证,但我不熟悉许多情况。

      您显然是在发送证书。服务器显然拒绝了它。

      这里缺少的信息是创建证书的确切方式以及提供者加载证书的方式,但现在可能已经全部结束了。

      【讨论】:

      • 感谢您提供更多信息。我希望它在未来可以帮助更多的人。我的问题最终被服务器的系统管理员团队“解决”坚持这是我们的证书的错,并迫使我们从另一个注册商处购买一个全新的证书。我相信这是可行的,因为新注册商的 CA 证书已经加载到他们的网关中(而不是被错误地添加以支持我们原始证书的 CA。)
      • 在跟踪这个问题的相同路径后,我发现服务器拒绝我的测试证书的原因是由于客户端使用了不正确的证书类型。事实证明,我的那个被标记为:X509v3 Extended Key Usage: TLS Web Server Authentication。客户端证书应该有X509v3 Extended Key Usage: TLS Web Client Authentication。所以根本原因是客户端提供了 Web 服务器证书而不是客户端证书。重新生成正确的客户端类型证书有效!
      • 使用 OpenVPN 的easyrsa 工具,创建客户端证书的命令是:build-client-full。例如:./easyrsa --subject-alt-name="DNS.1:*.ec2.internal" build-client-full exampleclient nopass
      猜你喜欢
      • 2014-09-05
      • 2014-04-15
      • 2013-06-06
      • 2016-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多