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.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 sslcontext 2.1.1
File Size Uploaded Provenance
sslcontext-2.1.1.tar.gz 114.8 kB With provenance Details

Built distribution (wheel)

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

Total release size: 217.8 kB

Release files / sslcontext-2.1.1.tar.gz

Download URL sslcontext-2.1.1.tar.gz
Size 114.8 kB
Tags Source
SHA-256 checksum
How to use checksums
35f7b206397ec3ea118f54c4772c3a9532a71289f34013ff813289538e9e77a5
BLAKE2b-256 checksum
How to use checksums
40568a8dcd5c76531729001de0cb25bd75fde4d53bd1173ab2b80d9834e0f3b5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 21, 2026.

Transparency log

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

Download URL sslcontext-2.1.1-py3-none-any.whl
Size 103.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
006f2ff8b67f33549ade693e45cb46c37cc40594d94b3be618e82afa38f709d0
BLAKE2b-256 checksum
How to use checksums
200d9fd4cfaeb81139759342cd31d7a27213972b4892056a039ef0082c82a7f4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 21, 2026.

Transparency log

Security for sslcontext 2.1.1

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.1.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 21, 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