Skip to content

Instantly share code, notes, and snippets.

@marshalhayes
Last active June 2, 2024 15:57
Show Gist options
  • Save marshalhayes/ca9508f97d673b6fb73ba64a67b76ce8 to your computer and use it in GitHub Desktop.
Save marshalhayes/ca9508f97d673b6fb73ba64a67b76ce8 to your computer and use it in GitHub Desktop.
TLS encryption of Python sockets using the "SSL" module

README.md

Follow these steps before trying to run any code.

  1. First, generate a Certificate Authority (CA).

openssl genrsa -out rootCA.key 2048

  1. Second, self-sign it.

openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 365 -out rootCA.pem

  1. Next, install that CA on the system(s) you want to use it on. You'll have to find out how/where to install it for your system.
  2. After that, create a certificate for each device you want to use it for.

openssl genrsa -out device.key 2048

Then, generate a certificate signing request.

openssl req -new -key device.key -out device.csr

Pay careful attention the "Common Name" field. It must be the same as the common name for the CA, even if it's an IP address.

  1. Then, sign the CSR using the root-CA.

openssl x509 -req -in device.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out device.crt -days 364 -sha256

  1. Finally, install the key and the certificate in your device(s).

References

import ssl
import socket
if __name__ == "__main__":
# Create a context, just like as for the server
context = ssl.create_default_context()
# Load the server's CA
context.load_verify_locations("/Users/marshalhayes/Projects/BlockchainPKI/rootCA.pem")
# Wrap the socket, just as like in the server.
conn = context.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM), server_hostname="localhost")
# Connect and send data! Standard python socket stuff can go here.
conn.connect(("localhost", 1234))
conn.sendall(b"Hello, server! This was encrypted.")
import ssl
import socket
BUFF_SIZE = 1024
if __name__ == "__main__":
# First, create a context. The default settings are probably the best here.
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
# Load the CA (self-signed, in this case) and the corresponding private key (also self-signed, in this case)
context.load_cert_chain(certfile="/Users/marshalhayes/Projects/BlockchainPKI/rootCA.pem",
keyfile="/Users/marshalhayes/Projects/BlockchainPKI/rootCA.key")
# Create a standard TCP socket, bind it to an address, and listen for connections
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("localhost", 1234))
s.listen()
# Start accepting incoming connections
accepting = True
try:
while accepting:
# conn is a standard python socket, addr is where it originated
conn, addr = s.accept()
# wrap the standard socket with the SSLContext, now it is a secure connection
with context.wrap_socket(conn, server_side=True) as secure_conn:
# data can be read/sent just like as in standard sockets
data = secure_conn.recv(BUFF_SIZE)
except socket.timeout:
pass
@tanjuntao
Copy link

Great, thanks for your sharing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment