Skip to main content

openssl-psk

TLS-PSK (pre-shared key) socket wrapper for Python 3.10+.
No compiled extensions — pure Python using the standard ssl module and ctypes.

pip install openssl-psk

Why this exists

The standard ssl module has no PSK support below Python 3.13.

openssl-psk works around this limitation by:

  • Calling libssl's SSL_CTX_set_psk_*_callback directly via ctypes on Python 3.10–3.12
  • Using the native SSLContext.set_psk_*_callback() API transparently on Python 3.13+

No C extension to compile. Just pip install.


Quick start

Client

import socket
from openssl_psk import wrap_socket_client

tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp.connect(("192.168.1.1", 4116))

# simplest form — just the key
ssl_sock = wrap_socket_client(tcp, psk=b"84155C93FDB08FB384B75C44A7D3B625")

ssl_sock.sendall(b"GET /resource HTTP/1.1\r\nHost: 192.168.1.1\r\n\r\n")
print(ssl_sock.recv(4096))
ssl_sock.close()

Server

import socket
from openssl_psk import wrap_socket_server

PSK_DB = {
    b"device-001": b"84155C93FDB08FB384B75C44A7D3B625",
    b"device-002": b"0AE9DF505E3D3B9A5305409550D42C96",
}

tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcp.bind(("0.0.0.0", 4116))
tcp.listen(5)

while True:
    conn, addr = tcp.accept()
    ssl_sock = wrap_socket_server(
        conn,
        psk=lambda identity: PSK_DB[identity],
        hint="my-server",                   # optional identity hint sent to clients
    )
    data = ssl_sock.recv(4096)
    ssl_sock.sendall(b"HTTP/1.1 200 OK\r\n\r\n")
    ssl_sock.close()

API

wrap_socket_client(sock, psk, ciphers=..., server_hostname=None)

Parameter Type Description
sock socket.socket Connected TCP socket to wrap
psk bytes | tuple | callable Pre-shared key — see accepted shapes below
ciphers str OpenSSL cipher string (default: PSK-AES128-CBC-SHA256)
server_hostname str | None SNI hostname passed to wrap_socket

Accepted psk shapes:

# 1. Just the key — identity sent to server is b''
wrap_socket_client(sock, psk=b"mypsk")

# 2. Key + client identity
wrap_socket_client(sock, psk=(b"mypsk", b"myidentity"))

# 3. Callable: server hint → key
PSK_FOR = {b"server1": b"abcdef", b"server2": b"123456"}
wrap_socket_client(sock, psk=lambda hint: PSK_FOR[hint])

Returns an ssl.SSLSocket after completing the handshake.


wrap_socket_server(sock, psk, hint=None, ciphers=...)

Parameter Type Description
sock socket.socket Accepted TCP socket to wrap (from socket.accept())
psk bytes | callable Pre-shared key — see accepted shapes below
hint str | None PSK identity hint sent to clients (optional)
ciphers str OpenSSL cipher string (default: PSK-AES128-CBC-SHA256)

Accepted psk shapes:

# 1. Just the key — same key accepted for every client identity
wrap_socket_server(sock, psk=b"mypsk")

# 2. Callable: client identity → key (raise to reject)
PSK_FOR = {b"clientA": b"abcdef", b"clientB": b"123456"}
wrap_socket_server(sock, psk=lambda identity: PSK_FOR[identity])

Returns an ssl.SSLSocket after completing the handshake.
When using a callable, raise any exception to reject the client.


Compatibility

Python Mechanism CPython only?
3.10 ctypes → libssl Yes
3.11 ctypes → libssl Yes
3.12 ctypes → libssl Yes
3.13+ ssl.SSLContext.set_psk_*_callback() No

The ctypes path reads the SSL_CTX* pointer out of CPython's PySSLContext struct at a fixed offset that has been stable across CPython 3.x. It will raise a RuntimeError with a clear message if the pointer is NULL, so you will know immediately if anything changes in a future CPython release.

Requires OpenSSL ≥ 1.0.1 (for PSK cipher support).


Running the tests

pip install pytest
pytest

License

MIT — see LICENSE.

Metadata

Release files for openssl-psk 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for openssl-psk 0.1.1
File Size Uploaded
openssl_psk-0.1.1.tar.gz 8.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for openssl-psk 0.1.1
File Interpreter ABI Platform
openssl_psk-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 16.2 kB

Release files / openssl_psk-0.1.1.tar.gz

Download URL openssl_psk-0.1.1.tar.gz
Size 8.8 kB
Tags Source
SHA-256 checksum
How to use checksums
7d1e4ec573ce806f77df12123cb718f84953f0023c38a7bbd92b67ec84fcae4e
BLAKE2b-256 checksum
How to use checksums
a1e1eb2a3f3591c16920510da017bab87b52718ac378048248df707725ebdf80
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 25, 2026.

Transparency log

Release files / openssl_psk-0.1.1-py3-none-any.whl

Download URL openssl_psk-0.1.1-py3-none-any.whl
Size 7.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0a4396ef6285620e145e2667aeeb78c56499e875ec5e5fbaf50c8b57f918c2fd
BLAKE2b-256 checksum
How to use checksums
3c2fb0c46c5551c6d5cd7e9d02fdb1df180651df9009dd397d2d189d8ca5800a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page