I am writing a peer-to-peer protocol wherein nodes can connect to each other and the connection should be encrypted using TLS with session keys agreed with Diffie-Hellman exchange. However, using any kind of certificates would be tedious because after a TLS connection is established, each pair of nodes would still have to mutually authenticate using a ECDSA challenge-response protocol (this using a cipher-suite not supported by OpenSSL).
How can I use Python standard library
sslmodule to make such a TLS connection that does not require setting up snake-oil certificates given that I can control theSSLContexton both client and server?How can I then authenticate using a challenge-response protocol after the TLS handshake has completed, in a way that would exclude the possibility of a Mallory using credential forwarding?
For part 1, one possibility is to use OpenSSL cipher suite with
AECDHfor exampleAECDH-AES256-SHA. For server the code would beand for client code you can use the following
Notably, the
:@SECLEVEL=0needs to be specified for it to work.For part 2 and the challenge-response protocol, you can use the channel binding function - the return value of
as part of the signed messages in the challenge-response protocol. This is a 96-bit value.
However, the security of this solution is far from perfect. Notably, using the
AECDHcipher seems to limit the connection to TLS 1.2, and there are attacks against theget_channel_binding(cb_type='tls-unique')that essentially halve the length of the value, i.e. the effective security would be only 48 bits.In TLS 1.3 there would be option to derive a longer value, namely
get_channel_bindingwith typetls-exporter, however it is not currently supported by Python 3 SSL module. On the other hand for TLS 1.3 it seems these anonymous Diffie-Hellman cipher suites are no longer a possibility.