OpenSSL has a basic I/O abstraction which is abbreviated as BIO.

This abstraction let's you encode raw stream to TLS and back in memory - without actually doing any network I/O.

Python 3.5 introduced an API to use this feature: https://docs.python.org/3/library/ssl.html#memory-bio-support.

I haven't found any samples/tutorials how to use these objects, so I'm going to describe it briefly.

SSLObject and MemoryBIO are the core objects to do TLS. SSLObject does the data encryption/decryption and MemoryBIO objects are used to feed data to SSLObject and receive it back.

The only way to create SSLObject is to use SSLContext.wrap_bio().

import ssl tls_in_buff = ssl . MemoryBIO () tls_out_buff = ssl . MemoryBIO () ctx = ssl . SSLContext ( ssl . PROTOCOL_SSLv23 ) ctx . load_cert_chain ( 'localhost.crt' , 'private_key.pem' ) tls_obj = ctx . wrap_bio ( tls_in_buff , tls_out_buff , server_side = True )

To decrypt data we write it into input MemoryBIO object and then read the raw data from SSLObject :

tls_in_buff . write ( sock . recv ( 4096 )) http_req = tls_obj . read () print ( http_req )

To encrypt data we write into SSLObject and then read the encrypted data from output MemoryBIO :

tls_obj . write ( b 'HTTP/1.1 200 OK \r

\r

' ) sock . sendall ( tls_out_buff . read ())

Basically encryption/decryption could be depicted as:

b'data' b'\x17\x03\x03\x00\x1c\xc1...' | | write() | | write() | v | +-----------+ | | input | | | MemoryBIO | | +-----------+ | | v v +-----------------------------+ | | | SSLObject | | | +-----------------------------+ | | | | read() v v +-----------+ b'data' | output | | MemoryBIO | +-----------+ | read() | V b'\x17\x03\x03\x00\x1c\xc1...'