Yann Bouteiller
Yann Bouteiller

Reputation: 77

Python: How to use Twisted for secure TLS communication using my own keys? (private use, no paid CA)

I am trying to achieve secure TLS communication between my private Twisted client and my private Twisted server over the Internet, using my own cryptographic keys.

By "secure", I mean I want to make sure my client is indeed talking to my server, and my server is indeed talking to my client, without the risk of a man-in-the-middle attack. I reckon this is possible thanks to the TLS support in Twisted but I am a bit lost and would really appreciate some guidance please.

Thus far we have done something like this, using a shared secret password at the protocol level:

# client:

from twisted.internet import ssl

reactor.connectSSL(
    host=ip_server,
    port=port_server,
    factory=MyClientFactory(),
    contextFactory=ssl.ClientContextFactory()
)
# server:

factory = MyServerProtocolFactory()
context = ssl.DefaultOpenSSLContextFactory('keys/private.key', 'keys/selfsigned.crt')
reactor.listenSSL(port_server, factory, context)

This approach runs, but, as you can see, only the server has a private key and certificate. In other words, a man-in-the-middle can pretend being our server's IP, and read the secret password from our client.

Can you help me understand why the client doesn't seem to require any kind of secret key in this code, and how to replace this by a secure approach please? Thanks!

Upvotes: 0

Views: 608

Answers (1)

Steffen Ullrich
Steffen Ullrich

Reputation: 123270

... only the server has a private key. In other words, a man-in-the-middle can pretend being our server's IP, and read the secret password from our client.

That's not how TLS works.

The server certificate and the matching private key is not used to encrypt the data, it is used to authenticate the server against the client to make sure that the client does not talk to a man in the middle. This authentication protects the key exchange, which is used to create symmetric keys for the encryption is both directions. So the application data are protected, even if only the server has certificate and key - provided that the client properly validates the certificate.

This works with both self-signed certificates and certificates issued by a publicly trusted CA. But with self-signed one needs to distribute the certificate or its fingerprint to the client before doing the TLS connection, since otherwise the client cannot properly validate the certificate from the server since it does not know what to expect.

But again, the client needs to properly validate the certificate. Your client does not since ClientContextFactory does not provide a context which validates certificates by default. Use instead optionsForClientTLS - see How to validate the SSL server certificate in twisted SSL client.

Upvotes: 2

Related Questions