Sans-IO Python implementation of the TLS 1.3 (RFC 8446) protocol stack
Project description
siotls
Sans-IO Python implementation of the TLS 1.3 (RFC 8446) protocol stack.
Quick Start
Install the library and select a cryptographic backend, openssl is a sane choice.
pip install siotls[openssl]
Use siotls.crypto.install to load the cryptography
backend you installed.
import siotls
siotls.crypto.install('openssl')
Client config
Create a client-side TLSConfiguration object.
A truststore is required to verify
the server certificates, leaving it out makes the configuration
insecure (as no certificate will be verified). The
get_truststore function attempts to locate
and load the truststore of the operating system, and fallbacks on using
certifi (Mozilla's bundled root CA certificates) if installed.
from siotls import TLSConfiguration
from siotls.trust import get_truststore
tls_client_config = TLSConfiguration(
side='client',
truststore=get_truststore(),
)
Server config
Create a server-side TLSConfiguration object.
Bth a private_key and
certificate_chain are required, they
must be in DER-format, the siotls.pem module offers
utilities to convert PEM to DER.
from siotls import TLSConfiguration
from siotls.pem import decode_pem_certificate_chain, decode_pem_private_key
with open('/path/to/private_key.pem', 'rb') as file:
der_private_key = decode_pem_private_key(file.read())
with open('/path/to/certificate_chain.pem', 'rb') as file:
der_certificate_chain = decode_pem_certificate_chain(file.read())
tls_server_config = TLSConfiguration(
side='server',
private_key=der_private_key,
certificate_chain=der_certificate,
)
Connection
Then establish a connection using your favorite network library and
create a TLSConnection object for that connection. The
following examples show a plain blocking socket client. A server
connection would be very similar.
import socket
from siotls import TLSConnection
tls_client_config = ... # above snippet
sock = socket.create_connection(('example.com', 443))
conn = TLSConnection(tls_client_config, server_hostname='example.com')
The next step is to exchange messages with the peer to secure the connection.
conn.initiate_connection()
if conn.config.side == 'client':
sock.sendall(conn.data_to_send())
while not conn.is_post_handshake():
if input_data := sock.recv(4096):
try:
conn.receive_data(input_data)
finally:
if output_data := conn.data_to_send():
sock.sendall(output_data)
else:
conn.close_receiving_end() # it goes post handshake
Exchange
The above while loop stops once the connection has been secured (or
closed). At this moment it is safe to exchange data, the following
example sends a basic HTTP request and prints the result.
req = """\
GET / HTTP/1.1\r
Host: example.com\r
Connection: close\r
\r
"""
res = bytearray()
if conn.is_connected():
conn.send_data(req.encode())
sock.sendall(conn.data_to_send())
while conn.is_connected():
if input_data := sock.recv(4096):
try:
conn.receive_data(input_data)
finally:
if output_data := conn.data_to_send():
sock.sendall(output_data)
res += conn.data_to_read()
else:
conn.close_receiving_end() # it disconnects
conn.close_sending_end()
sock.sendall(conn.data_to_send())
sock.close()
print(res.decode())
Documentation
Available online at readthedocs.io.
Contribute
The same as usual: fork, branch, pull request.
We are using uv and pre-commit:
# make sure to be in the right directory
cd path/to/siotls
# install dependencies in a venv
uv venv
uv sync --group precommit --group tests --group docs --extra hacl --extra openssl
uv run pre-commit install
# run tests
SIOTLS_INTEGRATION=1 uv run python -m unittest -v
# build docs
uv run sphinx-build -j auto docs/source/ docs/build/
Not all tests run by default, only the fast unittests do. Enable more
test suites setting the below environment variables to 1.
SIOTLS_INTEGRATION: tests that test more than a single function at a time.SIOTLS_SLOW: tests that make heavy use of the CPU.SIOTLS_EXTERNAL: tests that connect to remote servers on the internet.
The code is linted using ruff and isort, the typehints are validated using mypy. All of them run automatically with pre-commit, so you don't have any command to know.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file siotls-0.0.5.tar.gz.
File metadata
- Download URL: siotls-0.0.5.tar.gz
- Upload date:
- Size: 129.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.17
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a3b6c901c793e6c9411a557751c9444b37c8b6625304759615c1be0d50fdf65c
|
|
| MD5 |
e8bdfc9dd41c21d528af97ad9841c0f0
|
|
| BLAKE2b-256 |
83d4d4cb607793ccd0bd1a37c292fba9a027d8926d07cfa630af0edff171ac0e
|
File details
Details for the file siotls-0.0.5-py3-none-any.whl.
File metadata
- Download URL: siotls-0.0.5-py3-none-any.whl
- Upload date:
- Size: 128.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.17
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c08c21decb766101df475b1d361406638699604ae9f27bbad99afe9d339a4046
|
|
| MD5 |
320573c810eb80ccb5e7a0ccc220e944
|
|
| BLAKE2b-256 |
edb9a7dd6d7f5c327113036ac289eb82dc5c81cd90e527f9a9e32479e0ef8c26
|