Skip to main content

pypi version badge doc stable badge coverage badge

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.

Metadata

Release files for siotls 0.0.5

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

Source distribution (sdist)

Source distribution for siotls 0.0.5
File Size Uploaded Provenance Actions
siotls-0.0.5.tar.gz 129.4 kB Without provenance Details for siotls-0.0.5.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for siotls 0.0.5
File Interpreter ABI Platform Actions
siotls-0.0.5-py3-none-any.whl Python 3 none any Details for siotls-0.0.5-py3-none-any.whl

Total release size: 257.6 kB

Release files / siotls-0.0.5.tar.gz

Download URL siotls-0.0.5.tar.gz
Size 129.4 kB
Tags Source
SHA-256 checksum
How to use checksums
a3b6c901c793e6c9411a557751c9444b37c8b6625304759615c1be0d50fdf65c
BLAKE2b-256 checksum
How to use checksums
83d4d4cb607793ccd0bd1a37c292fba9a027d8926d07cfa630af0edff171ac0e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.17

Release files / siotls-0.0.5-py3-none-any.whl

Download URL siotls-0.0.5-py3-none-any.whl
Size 128.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c08c21decb766101df475b1d361406638699604ae9f27bbad99afe9d339a4046
BLAKE2b-256 checksum
How to use checksums
edb9a7dd6d7f5c327113036ac289eb82dc5c81cd90e527f9a9e32479e0ef8c26
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.17

Security for siotls 0.0.5

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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