当前位置: 首页 > 知识库问答 >
问题:

当服务器验证客户端证书失败时,Tls 1.3客户端不会报告握手失败

庾兴发
2023-03-14

我有一个使用OpenSSL的C客户机,在服务器上的SSL_do_handshake()调用期间,使用服务器端验证失败的证书时,该客户机的测试失败。当应用程序使用TLS 1.2时,服务器上的SSL_do_handshake()故障将在客户端调用SSL_do_handshake()作为故障返回值时报告给客户端。

在将我的应用程序升级到OpenSSL 1.1.1和TLS 1.3时,我注意到验证错误仍在服务器上发生,但不再向客户端报告。

我知道握手协议作为TLS 1.3的一部分被完全重写,但是看起来有了所有可用的各种回调,我应该能够在客户端以某种方式确定身份验证失败,而不必尝试向服务器写入数据。

还有其他人遇到过这种情况吗?他们能推荐一条前进的道路吗?

共有1个答案

孔寒
2023-03-14

TLSv1中的服务器和客户端。2和TLSv1。3考虑握手完成后,他们都写了一个“完成”的消息,并收到一个来自对等体。这就是TLSv1中握手的样子。2(取自RFC5246):

      Client                                               Server

      ClientHello                  -------->
                                                      ServerHello
                                                     Certificate*
                                               ServerKeyExchange*
                                              CertificateRequest*
                                   <--------      ServerHelloDone
      Certificate*
      ClientKeyExchange
      CertificateVerify*
      [ChangeCipherSpec]
      Finished                     -------->
                                               [ChangeCipherSpec]
                                   <--------             Finished
      Application Data             <------->     Application Data

因此,在这里您可以看到,客户机在与服务器的第二次通信中发送其证书和完成的消息。然后,它等待从服务器接收ChangeCipherSpec和完成的消息,然后再认为握手“完成”,并开始发送应用程序数据。

这是TLSv1的等效流量。3摘自RFC8446:

       Client                                           Server

Key  ^ ClientHello
Exch | + key_share*
     | + signature_algorithms*
     | + psk_key_exchange_modes*
     v + pre_shared_key*       -------->
                                                  ServerHello  ^ Key
                                                 + key_share*  | Exch
                                            + pre_shared_key*  v
                                        {EncryptedExtensions}  ^  Server
                                        {CertificateRequest*}  v  Params
                                               {Certificate*}  ^
                                         {CertificateVerify*}  | Auth
                                                   {Finished}  v
                               <--------  [Application Data*]
     ^ {Certificate*}
Auth | {CertificateVerify*}
     v {Finished}              -------->
       [Application Data]      <------->  [Application Data]

TLSv1的优点之一。3是它加快了完成握手所需的时间。在TLSv1中。3.客户端从服务器接收“已完成”消息,然后再发送其证书和已完成的消息。当客户端发送其“已完成”消息时,它已经收到“已完成”消息,因此握手已经完成,它可以立即开始发送应用程序数据。

当然,这意味着客户机在下次从服务器读取数据之前不知道服务器是否接受了证书。如果它已被拒绝,那么客户端将读取的下一个内容将是故障警报(否则将是正常的应用程序数据)。

我知道握手协议作为TLS 1.3的一部分被完全重写,但是看起来有了所有可用的各种回调,我应该能够在客户端以某种方式确定身份验证失败,而不必尝试向服务器写入数据。

重要的不是向服务器写入数据,而是读取数据。只有这样,您才能知道服务器是否发送了警报,或者只是发送了正常的应用程序数据。在读取数据之前,OpenSSL中没有任何回调可以告诉您这一点,因为由于底层协议的原因,OpenSSL本身不知道。

 类似资料:
  • 我不知道我到底需要在哪里包含客户机证书。现在,我的第一个问题是我不信任服务器。我尝试使用默认的Java密钥库文件(cacerts),其中包含Thawte和Digicert,这些是我试图与之通信的服务器的根权限。我使用

  • 问题内容: 我正在连接到以前成功使用过的Web服务,但是现在他们已经更改了主机名并向我发送了两个.pem文件。一个是CA,另一个是我的新客户证书。 (我将Java 1.5,Spring + Spring Web Services与Apache httpclient一起使用,但是我怀疑我的问题是证书,密钥和SSL本身。) 我已经导入了.pem文件以及从Firefox导出到cacerts中的主机的.c

  • 验证 SSH 服务器证书(客户端) 和 SSH 用户证书 类似,使用客户端机构认证来验证主机。需要一个 SSH 服务器数字证书认证机构签发服务器证书,客户端只需要保存 CA 的公钥。 使用一台处于气隙系统下的计算机来生成服务器数字证书认证机构的根证书: ❯ ssh-keygen -C "SSH Server Certificate Authority" -f sshserver.root.ca 使

  • 问题内容: 尝试获取网页: 获取https://www.fl.ru/:远程错误:握手失败。 如果我尝试获取另一个HTTPS页面-一切正常。 问题答案: 该服务器仅支持一些弱密码: 如果确实必须连接到该服务器,则Go会支持列表中的最后一个密码,但默认情况下不支持。使用新的tls.Config创建一个客户端,并指定所需的密码:

  • 尝试获取网页: 收到https://www.fl.ru/:远程错误:握手失败。 如果我尝试获取另一个HTTPS页面,一切都可以。

  • 我有一个客户端-服务器应用程序(Android客户端、Apache Http服务器),通过相互身份验证(TLS 1.2)进行通信。问题是:有时连接(登录)会因SSL错误而失败。 这是有效的: 注册客户端证书 登录 这是行不通的: 注册客户证书 注意:在步骤4之后杀死应用程序,然后启动它并执行步骤5工作。 我能想到的可能解释是: 正在重用一些旧资源(如旧客户端证书)。看起来所有相关的东西(OkHtt