Skip to main content

sslcontext

Version Python versions License: MIT Docs CI

Client certificates whose private keys never leave the OS keystore, in a plain ssl.SSLContext. sslcontext signs TLS handshakes through Windows CNG, the macOS Keychain or a PKCS#11 token (smart cards included), so every library that accepts an ssl_context gets mutual TLS with no patching, no temporary key files and no compiled extension; system_context() also picks the certificate as the browser would. Documentation: https://jose-pr.github.io/sslcontext/.

Features

  • Keystore identities in stdlib ssl — non-exportable and smart-card keys work, because the key is used through the keystore, never copied.
  • Pure Python — ctypes over the OpenSSL that Python itself loaded: an OpenSSL 3 provider on modern builds, an OpenSSL 1.1 engine on older ones.
  • In-memory credentials — load PEM or PKCS#12 bytes into a context without writing a key to disk.
  • Never blocks on a PIN — PINs and passwords come from a value or a callback you write; with none, operations fail at once. Keystore dialogs and PIN pads are opt-in.
  • The system's context — system_context(): the OS verifies servers (truststore) and, when a server asks, the client certificate is chosen as the browser would: from the system's keystores, matching the CAs the server names, following Edge's and Chrome's AutoSelectCertificateForUrls policy, your rules or your callback, and never blocking.
  • One context builder — create_context() for the verify/cafile/capath combinations every HTTP client reimplements.

Keystores

Backend Platform Keys Extra
cng Windows certificate stores: software (incl. non-exportable), TPM, smart cards and virtual smart cards, legacy CryptoAPI CSPs none
pkcs11 any PKCS#11 tokens: smart cards (real or virtual) via OpenSC, HSMs, TPMs, SoftHSM none

Installation

pip install sslcontext

Quick start

Behave like the system's browser: the OS verifies the server, and when a server asks for a client certificate the matching one is chosen from the system's keystores. Build it once and share it:

import urllib.request
import sslcontext

ctx = sslcontext.system_context()
urllib.request.urlopen("https://intranet.example.com/", context=ctx)

A client certificate and key, from files, PEM text, bytes, pathlib paths or cryptography objects alike:

import sslcontext

ctx = sslcontext.create_context(ca="ca.pem", certificate="client.pem", key=key_pem)

Use a certificate from the Windows store whose key cannot be exported:

import urllib.request
import sslcontext
from sslcontext.backends import CNGBackend

ctx = sslcontext.create_context()
sslcontext.load_identity(ctx, CNGBackend().find_identity(subject="alice"))
urllib.request.urlopen("https://mtls.example.com/", context=ctx)

Use a smart card through its PKCS#11 module. The PIN callback decides how the PIN is obtained; with no PIN, signing fails instead of waiting:

from getpass import getpass
from sslcontext.backends import PKCS11Backend

def pin(request: sslcontext.PinRequest):
    if request.purpose == "list":
        return None  # list without logging in
    return getpass(f"PIN for {request.token}: ")

card = PKCS11Backend(pin=pin)
sslcontext.load_identity(ctx, card.find_identity(subject="alice"))

API overview

Module Purpose
sslcontext context builders (system_context, create_context), identity loading, client certificate selection, the Signer contract
sslcontext.backends keystore backends and their registry
sslcontext.issuing a local certificate authority issuing server certificates
sslcontext.testing SoftwareSigner, an in-memory signer for tests
sslcontext.exceptions the package's errors

Command line

pip install "sslcontext[cli]" adds sslcontext: sslcontext list shows the client certificates the system's keystores hold, and sslcontext probe https://intranet.example/ shows what a server asks for and which certificate answers it.

Development

dotagents pyvenv && dotagents pyvenv 3.9
.pyvenv/<tag>/Scripts/python -m pip install -e ".[dev]"
.pyvenv/<tag>/Scripts/python -m pytest -q -rs

Releasing

This project follows Semantic Versioning and keeps a CHANGELOG.md. Pushing a tag matching v* triggers the release workflow: test gate → build (checking the tag names the version built) → a strict docs build as a gate → GitHub release → publish. The release workflow never deploys the docs site itself: for a final release its last job dispatches the docs workflow at the tag, which owns every Pages deploy.

License

MIT — see LICENSE.

Metadata

Release files for sslcontext 2.1.0

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

Source distribution (sdist)

Source distribution for sslcontext 2.1.0
File Size Uploaded Provenance
sslcontext-2.1.0.tar.gz 113.2 kB With provenance Details

Built distribution (wheel)

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

Total release size: 216.2 kB

Release files / sslcontext-2.1.0.tar.gz

Download URL sslcontext-2.1.0.tar.gz
Size 113.2 kB
Tags Source
SHA-256 checksum
How to use checksums
dca3bf4be4201c2f0ed32f804df5b04e73bc97f332be1c86b385050985caf6d5
BLAKE2b-256 checksum
How to use checksums
62101e13c1a0c653590007d5912e4a32db16065eeb232a4b9a9dd532680582f9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 19, 2026.

Transparency log

Release files / sslcontext-2.1.0-py3-none-any.whl

Download URL sslcontext-2.1.0-py3-none-any.whl
Size 103.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
cf48d90f1dd59064c05748f963d9f4c05d41ec19342171df0df9c53ee3d3de1d
BLAKE2b-256 checksum
How to use checksums
a8a00ffd45f239028c1c1d985faf55052ccb3f50c8cc46668ff6732e4d73fbe4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 19, 2026.

Transparency log

Security for sslcontext 2.1.0

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for sslcontext-2.1.0.tar.gz

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 Oct 19, 2026.

Transparency log

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.

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