Free cookie consent management tool by TermsFeed The SSLSocket class in Python | Pythontic.com

The SSLSocket class in Python

Overview:

  •  The SSLSocket class is derived from the socket class and represents a secure socket in TLS context.

  • The Python examples given here use SSLSocket instances in both server and client scenarios.

The SSLSocket class in Python

Example Server program that uses TLS:

  • The SSL server program creates a server socket and listens on port 15001 on localhost.
  • When a client connection is accepted, a client socket is created which is wrapped  into a SSLSocket.
  • The SSLSocket is supplied with the CA Certificate, the certificate of the server and the corresponding private key.
  • A call to the getpeercert() on the secure client connection(ie., the SSLSocket instance) gets the certificate of the client.
  • The server program validates the common Name, time validity  of the certificate before sending any information over the secure connection with the client.

# Example SSL server program that listens at port 15001.
# The server receives current timestamp requests from each 
# client that connects to it.
# If the TLS handshake is successful, it validates the following fields 
# from the client certificate : commonName, notBefore and notAfter. 
# If the verification succeeds the server sends the current timestamp 
# to the client using TLS.

import ssl
import socket
import datetime
import time
import os

# IP and port number
ipAddress   = "127.0.0.1";
port        = 15001;

# Create a server socket 
serverSocket = socket.socket();
serverSocket.bind((ipAddress, port));

# Listen for incoming connections
serverSocket.listen();
print("Server listening:");

while(True):
    # Keep accepting connections from clients
    (clientConnection, clientAddress) = serverSocket.accept();

    # Create an SSL Context 
    sslContext = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
    
    # Load the certificates from the certificate authority
    sslContext.load_verify_locations("./DemoCA.pem") 

    # Load the certificate and the private key
    sslContext.load_cert_chain("./DemoSvr.pem", keyfile = "./DemoSvr.key")

    # The program uses a self-signed root certificate.
    # The server certificate is self-signed by this CA.
    # Python3.13 is strict about self-signed certificates.
    # Hence, removing the strict policy from the SSLContext
    # Courtesy: https://github.com/redis/redis-py/issues/3685
    sslContext.verify_flags = sslContext.verify_flags & ~ssl.VERIFY_X509_STRICT
    
    # This is required. Without this getpeercert() will not get any client 
    # certificate at the server-side.
    sslContext.verify_mode  = ssl.CERT_REQUIRED
    
    # Make the socket connection to the clients secure through SSLSocket
    secureClientSocket = sslContext.wrap_socket(clientConnection, 
                                                server_side = True)
    
    # Get certificate from the client
    client_cert = secureClientSocket.getpeercert()
    print(type(client_cert))
    print("Client certificate(X.509):")
    print(client_cert)

    clt_subject    = dict(item[0] for item in client_cert['subject'])
    clt_commonName = clt_subject['commonName']

    # Check the client certificate bears the expected name as per server's policy
    if not client_cert:
        raise Exception("Unable to get the certificate from the client")
        
    if clt_commonName != 'DemoClient':
        raise Exception("Incorrect common name in client certificate")

    # Check time validity of the client certificate
    t1  = ssl.cert_time_to_seconds(client_cert['notBefore'])
    t2  = ssl.cert_time_to_seconds(client_cert['notAfter'])
    ts  = time.time()

    if ts < t1:
        raise Exception("Client certificate not yet active")
        
    if ts > t2:
        raise Exception("Expired client certificate")

    # Recieve communication from server
    data = secureClientSocket.recv(1024)
    print("Received from client:")
    print(data)

    # Send current server time to the client
    serverTimeNow = "%s"%datetime.datetime.now()
    secureClientSocket.send(serverTimeNow.encode(errors='ignore'))
    print("Securely sent %s to %s"%(serverTimeNow, clientAddress))

    # Close the connection to the client
    secureClientSocket.close()

 

Example Client program that uses TLS:

  • The client program makes use of the SSLContext instance to load the CA certificate, client certificate and the corresponding private key.  
  • The client creates a stream based socket and wraps it around an SSLSocket instance.
  • Through the SSLSocket instance the security aspects of the communication: Privacy, Data Integrity and Authentication are taken care.
  • Once the SSLSocket instance makes a connection to the server listening on a specific IP address and Port it requests for the certificate of the server to which it is connected to.
  • The fields of the certificate like commonName, notBefore and notAfter are validated before any communication is received from the server.

# Example TLS client(a.k.a SSL client) that connects to a 
# TLS server using a server_hostname. The client gets the X.509 
# certificate post TLS handshake and verifies it. 
# Post verification the client requests for the time at server 
# which it receives using the TLS protocol.
import socket
import ssl
import os
import time

# IP address and the port number of the server
sslServerIP    = "127.0.0.1"
sslServerPort  = 15001

# Create an SSL context
context                     = ssl.create_default_context()
context.check_hostname      = True


# Load CA certificate with which the client will 
# validate the server certificate
context.load_verify_locations("./DemoCA.pem")

# Ease the policy of Python3.13 towards self-signed certificates
context.verify_flags = context.verify_flags & ~ssl.VERIFY_X509_STRICT

# Load client certificate
context.load_cert_chain(certfile="./DemoClt1.pem", 
                        keyfile="./DemoClt1.key")

# Create a client socket
clientSocket        = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
severHostName       = "DemoServer"
# Make the client socket suitable for secure communication
secureClientSocket  = context.wrap_socket(clientSocket,
                                          server_hostname=severHostName,
                                          server_side=False)
secureClientSocket.connect(("127.0.0.1", sslServerPort))

# Obtain the certificate from the server
server_cert = secureClientSocket.getpeercert()
print("X.509 certificate of the server %s:"%severHostName)
print(server_cert)

# Validate whether the Certificate is indeed issued to the server
subject         = dict(item[0] for item in server_cert['subject'])
commonName      = subject['commonName']

if not server_cert:
    raise Exception("Unable to retrieve server certificate")
    
if commonName != 'DemoServer':
    raise Exception("Incorrect common name in server certificate")

notAfterTimestamp   = ssl.cert_time_to_seconds(server_cert['notAfter'])
notBeforeTimestamp  = ssl.cert_time_to_seconds(server_cert['notBefore'])
currentTimeStamp    = time.time()

if currentTimeStamp > notAfterTimestamp:
    raise Exception("Expired server certificate")
    
if currentTimeStamp < notBeforeTimestamp:
    raise Exception("Server certificate not yet active")

# Safe to proceed with the communication
secureClientSocket.send(b"Time request:")
msgReceived = secureClientSocket.recv(1024)
print("Secure communication received from server:%s"%msgReceived.decode())

# Close the sockets
secureClientSocket.close()
clientSocket.close()

Output - Server:

Server listening:
<class 'dict'>
Client certificate(X.509):
{'subject': ((('countryName', 'IN'),), (('stateOrProvinceName', 'KA'),), (('localityName', 'BLR'),), (('organizationName', 'DemoClientOrg'),), (('organizationalUnitName', 'DemoClientUnit'),), (('commonName', 'DemoClient'),), (('emailAddress', 'democlient@democlienttesting.com'),)), 'issuer': ((('countryName', 'IN'),), (('stateOrProvinceName', 'KA'),), (('localityName', 'BLR'),), (('organizationName', 'DemoCAOrg'),), (('organizationalUnitName', 'DemoCAUnit'),), (('commonName', 'localca'),), (('emailAddress', 'localca@localcatest.com'),)), 'version': 1, 'serialNumber': '01', 'notBefore': 'Sep 22 10:58:45 2025 GMT', 'notAfter': 'Sep 22 10:58:45 2026 GMT'}
Received from client:
b'Time request:'
Securely sent 2025-09-23 22:28:13.751038 to ('127.0.0.1', 59087)

Output - Client:

X.509 certificate of the server DemoServer:
{'subject': ((('countryName', 'IN'),), (('stateOrProvinceName', 'KA'),), (('localityName', 'BLR'),), (('organizationName', 'DemoServerOrg'),), (('organizationalUnitName', 'DemoServerUnit'),), (('commonName', 'DemoServer'),), (('emailAddress', 'demoserver@demoservertesting.com'),)), 'issuer': ((('countryName', 'IN'),), (('stateOrProvinceName', 'KA'),), (('localityName', 'BLR'),), (('organizationName', 'DemoCAOrg'),), (('organizationalUnitName', 'DemoCAUnit'),), (('commonName', 'localca'),), (('emailAddress', 'localca@localcatest.com'),)), 'version': 1, 'serialNumber': '01', 'notBefore': 'Sep 22 10:44:04 2025 GMT', 'notAfter': 'Sep 22 10:44:04 2026 GMT'}
Secure communication received from server:2025-09-23 22:28:13.751038


Copyright 2025 © pythontic.com