代码之家  ›  专栏  ›  技术社区  ›  e-info128

如何在python中使用ssl解决握手失败问题?

  •  1
  • e-info128  · 技术社区  · 6 年前

    我尝试连接到特定的https服务器:

    socketHandler = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    socketWraped = ssl.wrap_socket(socketHandler)
    socketWraped.connect(('certificatedetails.com', 443))
    

    但是巨蟒说:

    File "/usr/lib/python3.6/ssl.py", line 1109, in connect
    self._real_connect(addr, False)
    File "/usr/lib/python3.6/ssl.py", line 1100, in _real_connect
    self.do_handshake()
    File "/usr/lib/python3.6/ssl.py", line 1077, in do_handshake
    self._sslobj.do_handshake()
    File "/usr/lib/python3.6/ssl.py", line 689, in do_handshake
    self._sslobj.do_handshake()
    ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:852)
    

    我尝试使用tls1:

    socketWraped = ssl.wrap_socket(
        socketHandler,
        ssl_version=ssl.PROTOCOL_TLSv1,
        ciphers='ADH-AES256-SHA'
    )
    

    但他说:

    ssl.SSLError: [SSL: NO_CIPHERS_AVAILABLE] no ciphers available (_ssl.c:852)
    

    在python和操作系统中升级ssl:

    $ hostnamectl
       Static hostname: machine
             Icon name: computer-desktop
               Chassis: desktop
            Machine ID: ...
               Boot ID: ...
      Operating System: Ubuntu 18.04.2 LTS
                Kernel: Linux 4.15.0-51-generic
          Architecture: x86-64
    $ openssl version
    OpenSSL 1.1.1c  28 May 2019
    $ python3 -c "import ssl; print(ssl.OPENSSL_VERSION)"
    OpenSSL 1.1.1c  28 May 2019
    

    从netcat可以无问题地连接:

    $ ncat --ssl -v certificatedetails.com 443
    Ncat: Version 7.60 ( https://nmap.org/ncat )
    Ncat: SSL connection to 104.28.6.163:443.
    Ncat: SHA-1 fingerprint: 75B3 C6AD 7A72 62B5 7104 0632 0585 A82A F542 641B
    

    问题是什么,如何解决?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Joseph Sible-Reinstate Monica    6 年前

    the documentation 以下内容:

    由于Python3.2和2.7.9,建议使用 SSLContext.wrap_socket() 一个 SSLContext 实例将套接字包装为 SSLSocket 物体。helper函数 create_default_context() 返回具有安全默认设置的新上下文。旧的 wrap_socket() 函数已被弃用,因为它既低效又 不支持服务器名称指示(SNI)和主机名匹配。

    当我使用sslcontext.wrap_socket()而不是不推荐使用的wrap_socket()时,它可以工作:

    socketHandler = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    socketWraped = ssl.create_default_context().wrap_socket(socketHandler, server_hostname='certificatedetails.com')
    socketWraped.connect(('certificatedetails.com', 443))