代码之家  ›  专栏  ›  技术社区  ›  user740521

SSL连接在没有客户端身份验证的情况下失败

  •  1
  • user740521  · 技术社区  · 6 年前

    我了解到客户端身份验证是可选的,因此我尝试连接到SSL服务器,而不在客户端进行身份验证。执行此操作时,服务器上出现以下错误:

    , in accept_connection
        ssl_version=ssl.PROTOCOL_SSLv23
      File "/usr/lib/python2.7/ssl.py", line 933, in wrap_socket
        ciphers=ciphers)
      File "/usr/lib/python2.7/ssl.py", line 601, in __init__
        self.do_handshake()
      File "/usr/lib/python2.7/ssl.py", line 830, in do_handshake
        self._sslobj.do_handshake()
    SSLEOFError: EOF occurred in violation of protocol (_ssl.c:590)
    

    这是工作的服务器和客户端代码,当我在客户端进行身份验证时,一切正常,但当我对该行进行注释时,错误就会显示出来。

    服务器(python):

    def accept_connection(self, sock):
        client, (addr, port) = sock.accept()
        sslclient = ssl.wrap_socket(
            client,
            server_side=True,
            certfile=self.ssl_cert_file,
            keyfile=self.ssl_key_file,
            ssl_version=ssl.PROTOCOL_SSLv23
        )
    

    客户端(C#):

    public bool Connect()
        {
            try
            {
                client = new TcpClient(this.ServerAddress, this.ServerPort);
    
                sslStream = new SslStream(
                    client.GetStream(),
                    false,
                    new RemoteCertificateValidationCallback(ValidateCert),
                    null
                );
    
                try
                {
                    sslStream.AuthenticateAsClient(this.ServerAddress);
                }
                catch (AuthenticationException e)
                {
                    sslStream = null;
                    client.Close();
                    client = null;
                    return false;
                }
            }
            catch (Exception e)
            {
                return false;
            }
    
            return true;
        }
    

    以上是没有错误的工作代码。

    当我在客户端上注释掉以下代码时:

    //sslStream.AuthenticateAsClient(this.ServerAddress);
    

    出现上述python错误,客户端连接不会引发任何异常并继续运行,直到第一次读取为止,然后出现以下故障:

    This operation is only allowed using a successfully authenticated context.
    

    如果我不打电话,我该怎么做 AuthenticateAsClient ?

    这是我如何生成certfile和keyfile的

    openssl req -x509 -newkey rsa:1024 -keyout my.key -out my.crt -days 365 -nodes -subj "/C=US/ST=VA/L=Junk/O=None/OU=Junk/CN=example.local"
    

    Python是版本2。

    也许我只是被错误地告知 AuthenticateAscient 是否可选?

    1 回复  |  直到 6 年前
        1
  •  2
  •   Evk    6 年前

    Ssl 客户端证书 身份验证确实是可选的。客户端将其证书发送到服务器,服务器验证此证书是否有效,这是服务器所期望的,并使用该证书对客户端进行身份验证。

    然而,这并不是由

    sslStream.AuthenticateAsClient(this.ServerAddress);
    

    正如文档所述,此方法是

    客户端调用 验证服务器 以及可选的客户端 在客户端-服务器连接中。

    验证服务器(验证其证书是否有效、是否为预期域颁发、是否由受信任的机构颁发)是ssl握手中必需的步骤。例如,使用描述方式 this link 我们看到第3步是:

    SSL或TLS客户端验证服务器的数字证书

    服务器等待来自客户端的此步骤的结果继续。因此,如果您通过对调用进行注释来跳过此步骤 AuthenticateAsClient -您的python服务器正确地投诉协议冲突。

    要使用客户端身份验证,请使用另一个重载:

    X509CertificateCollection clientCerts = GetClientCerts();
    sslStream.AuthenticateAsClient(this.ServerAddress, clientCerts, true);
    

    因为您没有这样做,所以您没有执行(可选)客户端身份验证。