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

Ssl 当服务器验证客户端证书失败时,Tls 1.3客户端不报告握手失败,ssl,openssl,tls1.3,Ssl,Openssl,Tls1.3,我有一个使用OpenSSL的C客户机,在服务器上调用SSL_do_handshake()期间,使用服务器端验证失败的证书时测试失败。当应用程序使用TLS 1.2时,服务器上的SSL_do_handshake()故障将在客户端调用SSL_do_handshake()作为故障返回值时报告给客户端 在将我的应用程序升级到OpenSSL 1.1.1和TLS 1.3时,我注意到,虽然验证错误仍在服务器上发生,但不再向客户端报告 我知道作为TLS 1.3的一部分,握手协议被完全重写了,但是似乎有了所有各种回

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

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

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


有没有其他人遇到过这样的问题,他们能推荐一条路径吗?

< P> TLSV1.2和TLVS1.3中的服务器和客户端都认为当他们写了一个“完成”的消息,并从对等体收到一个握手时,握手就完成了。这是TLSv1.2中握手的样子(取自RFC5246):

客户端服务器
克利恩泰罗---------------->
服务器你好
证书*
服务器密钥交换*
证书申请*
[更改密码规范]
服务器你好^Key
+密钥共享*| Exch
+预共享密钥*v
{EncryptedExtensions}^服务器
{CertificateRequest*}v参数
{证书*}^
{CertificateVerify*}认证
{Finished}v
[申请资料][申请资料]
TLSv1.3的优点之一是它加快了完成握手所需的时间。在TLSv1.3中,客户端从服务器接收“已完成”消息,然后再发送其证书和已完成消息。当客户端发送“Finished”消息时,它已经收到了“Finished”,因此握手已经完成,它可以立即开始发送应用程序数据

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

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


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

感谢您的解释。这是有道理的。正如我前面提到的,我的客户机代码仅依赖于函数SSL_do_handshake()返回一个错误来检测服务器是否有任何证书错误。我在客户机中添加了这个附加检查:
chara;if(recv(&a,1,MSG_PEEK)==0)返回false;}但是,尽管我知道服务器指示了握手错误,但我看到客户机中的recv()调用在您描述的情况下会成功,我预计它会失败。如果服务器失败,它会向客户机发送警报。这是TLS级别的错误消息。recv()只在TCP级别工作,因此它将成功地看到“某物”的到来。由OpenSSL来解释它,确定它是一个错误警报,只有这样客户端才会失败。我从
recv()
切换到
SSL\u read()
,这也表示读取成功。很抱歉,我太过密集,我应该如何使用OpenSSL检查以解释返回的内容并确定它是否是错误警报?如果您收到警报,那么SSL_read()应该返回哦,好的。很抱歉,我知道了
SSL\u get\u error()
我没有看到任何返回的错误,所以我想一定是我错过了API的其他部分。我必须再次检查我的代码,看看为什么服务器
SSL\u do\u handshake()
故障没有在客户端触发读取错误。谢谢你的帮助。
      Client                                               Server

      ClientHello                  -------->
                                                      ServerHello
                                                     Certificate*
                                               ServerKeyExchange*
                                              CertificateRequest*
                                   <--------      ServerHelloDone
      Certificate*
      ClientKeyExchange
      CertificateVerify*
      [ChangeCipherSpec]
      Finished                     -------->
                                               [ChangeCipherSpec]
                                   <--------             Finished
      Application Data             <------->     Application Data
       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]