[Solved] Python SSL handshake failure after upgrading MacOS To Monterey

After upgrading MacOS To Monterey 12.0.1, I suddenly found that the original working Python 3 failed to request Huawei restconf API, prompting   ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:1129)  , The curl provided with the MAC also fails to shake hands with the Huawei API, prompting   curl: (35) error:06FFF089:digital envelope routines:CRYPTO_ internal:bad key length  。

Libressl is used by default on the Mac platform instead of OpenSSL. SSL version information: libressl 2.8.3, curl version information: curl 7.77.0 (x86_64 Apple Darwin 21.0) libcurl/7.77.0 (securetransport) libressl/2.8.3 zlib/1.2.11 nghttp2/1.42.0.

The SSL handshake process is checked by capturing packets. It is found that curl and python 3 perform differently.

The above figure shows the handshake process of curl. You can see that the key exit has been completed, but the client actively closes the connection for some reason, and then the server reports an error.

The above figure shows the handshake interaction of Python 3 calling the http.client.httpsconnection library. You can see that the server directly reports an error just after issuing the client hello.

It is also Python 3, which is no problem on Linux, and it is no problem for Python 3 on Mac to shake hands with other HTTPS websites. Comparing the handshake capture on Linux and MAC, we can see that there are more fields in the client Hello sent by MAC. After technical communication with Huawei, he said that Huawei’s restconf API does not support tls1.3 protocol, which he believes is the reason for the handshake failure.

You can see that although SSL on Linux also supports tls1.3, it is not supported during the handshake process_ For the extension of versions, try to disable tls1.3 in Python, and the test result is that the handshake is successful.

The solution is as follows:

from ssl import _create_unverified_context
ctx = _create_unverified_context()
ctx.set_ciphers('ALL')
ctx.options &= ~ssl.OP_NO_SSLv3  #allow ssl3.0, default is forbid
ctx.options |= ssl.OP_NO_TLSv1_3  #forbid tls1.3,default is allow
opener = HTTPSConnection('xx.xx.xx.xx', port=443, timeout=3, context=ctx)

If you use urllib3 or request library, you can also modify the context here.

The above methods are supported in versions after Python 3.2. Versions before Python 3.2 can also use the following methods:

ctx = _create_unverified_context(ssl.PROTOCOL_TLSv1_2)

This constant has been removed after Python 3.6. You can only use the previous method.

Unfortunately, the problem of curl failure has not been solved. Many people are waiting for apple to fix it on the Internet.

Similar Posts: