API Reference
Every public name, generated from the package's own docstrings.
The same surface in prose, with the bounds and the gotchas, is the API header
that ships inside the installed package, sslcontext/AGENTS.md, readable with
importlib.resources.files("sslcontext") and printed in the Guide of this site.
Client identities from OS keystores in a standard :class:ssl.SSLContext.
VerifyLike = Union[bool, str, 'os.PathLike[str]', None]
module-attribute
True/False, or a CA bundle file or hashed CA directory to trust.
HASHES = ('sha1', 'sha224', 'sha256', 'sha384', 'sha512')
module-attribute
Hash names a signer may be asked to sign for, as :mod:hashlib spells them.
BytesOrText = Union[bytes, bytearray, memoryview, str]
module-attribute
PEM text as str, or bytes holding PEM or DER.
PasswordSource = Union[str, bytes, 'os.PathLike[str]', Any, Callable[[], Union[str, bytes, None]], None]
module-attribute
A password (str or bytes), a file holding it (os.PathLike, or
an object with open() or read(): its first line, without the line
ending), a callable returning one (or None to decline), or None.
PinCallback = Callable[[PinRequest], Union[str, Prompt, None]]
module-attribute
Returns the PIN, :data:KEYSTORE_PROMPT, or None to decline.
PinSource = Union[str, Prompt, PinCallback, None]
module-attribute
A PIN, :data:KEYSTORE_PROMPT, a :data:PinCallback, or None (no PIN:
fail instead of asking anyone).
CertificateLike = Union[str, bytes, bytearray, memoryview, 'os.PathLike[str]', Any]
module-attribute
One certificate source: PEM text (a str holding a PEM header), PEM or
DER bytes, a path (str without a PEM header, or os.PathLike), an
object with open() (pathlib.Path and its kin, zip paths, package
resources), a readable file object, or a cryptography certificate.
CertificatesLike = Union[CertificateLike, Iterable[CertificateLike]]
module-attribute
One source, or a list or tuple of them.
KeyLike = Union[str, bytes, bytearray, memoryview, 'os.PathLike[str]', Any]
module-attribute
A private key from the same sources, or a cryptography private key.
Chooser = Callable[[CertificateRequest, List[Identity]], Optional[Identity]]
module-attribute
Picks one of the candidates, or None to send no certificate.
IdentitySource = Union['Backend', Identity, Callable[[], Iterable[Identity]]]
module-attribute
A keystore backend, one identity, or a callable returning identities.
CertificateInfo(subject, issuer, serial, not_before, not_after, sha1, sha256, key_type, key_bits)
dataclass
What a certificate says about itself, decoded by OpenSSL.
subject
instance-attribute
RFC 4514 distinguished name, e.g. CN=alice,O=Example.
serial
instance-attribute
Serial number in upper-case hexadecimal.
not_after
instance-attribute
Validity bounds, timezone-aware UTC.
sha1
instance-attribute
SHA-1 thumbprint of the DER certificate, upper-case hex (Windows' "Thumbprint").
key_type
instance-attribute
"rsa", "ec" or "other".
valid_at(when=None)
Whether when (default: now) lies inside the validity period.
Source code in src/sslcontext/_identity.py
77 78 79 80 | |
Identity(certificate, signer, chain=(), label='')
dataclass
A certificate, its chain, and a signer for its private key.
certificate and each entry of chain are DER bytes; chain runs
from the issuer of certificate upward and may omit the root.
info
cached
property
The decoded certificate. Raises CredentialError if it is malformed.
Padding
Bases: Enum
RSA signature padding. ECDSA signatures have none.
Signer
Bases: Protocol
Signs a digest with a private key the caller cannot see.
Implemented by every keystore backend, and by anything else that can sign: a remote HSM, a cloud KMS, a test key.
A signer may also have a supports_pss attribute. When it is
False for an RSA key, :func:load_identity keeps the context's own
signatures to PKCS#1 v1.5, which limits that identity to TLS 1.2.
sign(digest, *, hash, padding=None, salt_length=None)
Return the signature of digest, already hashed with hash.
hash is one of :data:HASHES. For an RSA key padding is set;
with :attr:Padding.PSS, salt_length is the salt length in bytes
and MGF1 uses hash. For an EC key padding is None and the
result is a DER-encoded ECDSA signature. Raising any exception fails
the handshake.
Called from the thread performing the TLS handshake, with OpenSSL
mid-operation: a signer must not use the same ssl.SSLContext.
Source code in src/sslcontext/_identity.py
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | |
PinRequest(backend, token, certificate, purpose, keystore_prompt)
dataclass
What a PIN callback is told. It never contains a PIN.
backend
instance-attribute
The backend asking: "cng" or "pkcs11".
token
instance-attribute
The token's label (PKCS#11), or the key's container name (CNG).
certificate
instance-attribute
Subject of the certificate whose key needs the PIN; "" when the
request is not about one key (logging in to list a token).
purpose
instance-attribute
"list": logging in to see private keys; declining only hides
them. "sign": logging in before a signature; declining fails it.
"per-signature": the key demands the PIN for every signature
(CKA_ALWAYS_AUTHENTICATE, a PIV card's signature key).
keystore_prompt
instance-attribute
Whether returning :data:KEYSTORE_PROMPT can work here (the token has
a PIN pad, or Windows can show its dialog).
Prompt
Bases: Enum
Sentinels a PIN source may give instead of a PIN.
KEYSTORE = 'keystore'
class-attribute
instance-attribute
Let the keystore ask the user itself: Windows' PIN dialog, a reader's PIN pad. Waits for the user, so it is never the default.
AutoSelectRule(pattern, issuer=None, subject=None)
dataclass
Pick a certificate without asking, as Chrome's and Edge's
AutoSelectCertificateForUrls policy does.
pattern is a host pattern: example.com (that host),
[*.]example.com (it and every subdomain), *.example.com (the
subdomains), * (any host). A scheme, port or path in it is accepted
and ignored: the request knows only the server name. issuer and
subject filter the certificate: a mapping of RFC 4514 attributes to
exact values ({"CN": "Corp CA"}, as the policy's ISSUER/SUBJECT),
or a string matched as a case-insensitive substring of the whole name.
CertificateRequest(host, authorities, authorities_der, key_types, rsa_pss_required, tls_version)
dataclass
What a server asked for when it requested a client certificate.
host
instance-attribute
The server name the client sent (SNI); None when it sent none.
authorities
instance-attribute
RFC 4514 names of the CAs the server accepts; empty means any.
key_types
instance-attribute
"rsa" and/or "ec": key types the server's signature algorithms allow.
rsa_pss_required
instance-attribute
An RSA key must sign RSA-PSS (TLS 1.3, or a server offering no PKCS#1).
tls_version
instance-attribute
"TLSv1.3", "TLSv1.2", ...
ClientCertificateSelector(sources, *, choose=None, rules=(), browser_policy=False, remember=True, cache_ttl=60.0)
Answers a server's certificate request with an identity from sources.
Candidates are the identities a browser would offer: valid now, usable
for client authentication (no extended key usage, clientAuth or
anyExtendedKeyUsage; digitalSignature when key usage is present),
of a key type the server's signature algorithms allow (an RSA key that
cannot sign PSS is left out where PSS is required), and, when the server
names CAs, issued under one of them (the leaf's issuer or any certificate
of its chain). Newest expiry first.
The choice, in order: the identity remembered for the host, the first
of rules matching the host with a matching candidate, the same for
the browsers' policies when browser_policy is true (see
:func:browser_policies), choose(request, candidates), and, with no
choose, the only candidate when there is exactly one. Otherwise no
certificate is sent and the server decides.
Sources are listed again after cache_ttl seconds. A source that fails
is logged and skipped. An exception from choose (or a result that is
not one of the candidates) fails that handshake.
Source code in src/sslcontext/_select.py
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | |
identities()
Every identity the sources hold, listed at most every cache_ttl.
Source code in src/sslcontext/_select.py
219 220 221 222 223 224 225 226 | |
policies()
The browsers' rules (empty unless browser_policy), cached.
Source code in src/sslcontext/_select.py
242 243 244 245 246 247 248 249 250 251 252 253 | |
refresh()
List the sources and read the policies again on the next request.
Source code in src/sslcontext/_select.py
255 256 257 258 | |
forget(host=None)
Forget the choice made for host, or for every host.
Source code in src/sslcontext/_select.py
260 261 262 263 264 265 266 | |
candidates(request)
The identities a browser would offer for request, newest expiry first.
Source code in src/sslcontext/_select.py
298 299 300 301 302 303 304 305 306 307 308 309 310 | |
select(request)
The identity to answer request with, or None for none.
Source code in src/sslcontext/_select.py
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 | |
install(context)
Answer every certificate request on context from now on.
A client context only; it replaces a selector installed before. An
identity loaded with :func:~sslcontext.load_identity is still sent
when this selector picks none. context keeps the selector alive.
Source code in src/sslcontext/_select.py
378 379 380 381 382 383 384 385 386 387 388 | |
CredentialError
Bases: SSLContextError, ValueError
A certificate or key is malformed, encrypted with another password, or does not match its certificate.
IdentityNotFoundError
Bases: SSLContextError, LookupError
No keystore entry matched the query.
KeystoreError
Bases: SSLContextError, OSError
The keystore refused or failed an operation; errno holds its code.
SigningError
Bases: SSLContextError
The signer failed while OpenSSL was performing a handshake.
SSLContextError
Bases: Exception
Base class for every error this package raises.
UnsupportedOpenSSLError
Bases: SSLContextError
The interpreter's OpenSSL cannot be driven by this package.
LibreSSL, OpenSSL older than 1.1.1, and a statically linked _ssl that
hides its symbols all raise this.
create_context(purpose='client', *, verify=None, cafile=None, capath=None, cadata=None, ca=None, certificate=None, key=None, password=None, identity=None, minimum_version=None, maximum_version=None, alpn=None)
A context for purpose "client" or "server".
verify decides whether the peer's certificate is checked. None
means the purpose's default: a client verifies the server, a server does
not ask for a client certificate. True turns checking on (a server
then requires a client certificate), False turns it off (a client
also stops checking the host name). A path is shorthand for trusting that
CA bundle file or hashed directory, as in requests.
Trust comes from ca/cafile/capath/cadata when any is
given, and from the platform's default store otherwise. ca takes the
CA certificates themselves or where they are, in any form
:data:CertificatesLike names, one or a list.
certificate (leaf first, then its chain; one source or a list),
key and password load the context's own certificate as
:func:load_pem does; identity (an :class:Identity) as
:func:load_identity does. SSLKEYLOGFILE is honoured as by
:func:ssl.create_default_context.
Source code in src/sslcontext/_context.py
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | |
load_identity(context, identity)
Make a keystore :class:Identity the context's certificate and key.
The private key stays wherever identity.signer keeps it: OpenSSL asks
the signer for each handshake signature. The signer is held until
context is garbage-collected.
Raises :class:CredentialError for a malformed certificate,
:class:UnsupportedOpenSSLError when the interpreter's OpenSSL cannot
host the signer, and TypeError for arguments of the wrong type.
Source code in src/sslcontext/_load.py
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 | |
load_pem(context, certificate, key=None, password=None)
Load a certificate, its chain and its private key.
certificate is the leaf followed by any chain certificates: PEM
holding them in order, one DER certificate, or a list of sources (each
PEM or DER) in that order, in any form :data:CertificatesLike names
(text, bytes, paths, objects with open(), cryptography
certificates). It may instead be one PKCS#12 bundle (.p12/.pfx),
loaded as :func:load_pkcs12 loads it, with no key. key is a
PEM or DER private key (DER: PKCS#8, encrypted or not, or traditional),
likewise, or a cryptography private key; when omitted it is read from
the first certificate source, which then holds both. password (a
value, or a callable asked only if the key or bundle turns out
encrypted) decrypts it. Nothing is written to disk.
Raises :class:CredentialError for malformed data, a wrong password, or a
key that does not match the certificate; OSError when a named file
cannot be read.
Source code in src/sslcontext/_load.py
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | |
load_pkcs12(context, data, password=None)
Load the key, certificate and chain of a PKCS#12 (.p12/.pfx) bundle.
data is the bundle's bytes, its path, or an object with open() or
read(). Raises :class:CredentialError for a malformed bundle or a
wrong password, OSError when a named file cannot be read.
Source code in src/sslcontext/_load.py
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | |
browser_policies()
The AutoSelectCertificateForUrls rules set for Edge, Chrome and
Chromium on this machine, machine-wide before per-user, in each
browser's order. Empty when none is set; never raises for a policy that
cannot be read.
Source code in src/sslcontext/_policy.py
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | |
rules_from_policy(entries)
Rules from policy entries (JSON text or decoded objects), in order. A malformed entry is logged and skipped, as the browsers skip it.
Source code in src/sslcontext/_policy.py
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | |
system_context(*, selector=None, pin=None, verify=None, ca=None, cafile=None, capath=None, cadata=None, certificate=None, key=None, password=None, identity=None, minimum_version=None, maximum_version=None, alpn=None)
A client context that behaves as the system's own clients do.
Servers are verified by the operating system (truststore: CryptoAPI
on Windows, the Security framework on macOS, the system store elsewhere)
on Python 3.10 and later, and by OpenSSL over the default store on 3.9.
A verify, ca, cafile, capath or cadata means what it
means to :func:create_context and replaces the system's trust.
A server's certificate request is answered by selector: by default
:func:system_selector (pin=pin); False sends no certificate.
A certificate (with key and password) or an identity is
loaded as by :func:create_context and is then the one sent: the
default selector is not installed unless selector asks for it. TLS
1.3 post-handshake requests are accepted. One context serves every
server and may be shared between threads.
Source code in src/sslcontext/_system.py
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | |
system_selector(*, pin=None, choose=None, rules=(), browser_policy=True, remember=True, cache_ttl=60.0)
A :class:ClientCertificateSelector over :func:system_sources,
following the browsers' AutoSelectCertificateForUrls policy.
Source code in src/sslcontext/_system.py
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | |
system_sources(*, pin=None)
The keystores a browser on this system offers client certificates from.
Windows: the user's Personal store (CNGBackend("MY")), which also
holds the certificates of inserted smart cards. macOS: the Keychain
(KeychainBackend(): the user's keychains and smart cards). Elsewhere:
the PKCS#11 module :class:~sslcontext.backends.PKCS11Backend would load
by default (p11-kit's proxy on Linux, every token the system configured),
when one is installed. pin is given to each backend. Nothing is opened here.
Source code in src/sslcontext/_system.py
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | |
Keystore backends
Keystores that hold identities: the contract, the registry, the built-ins.
A backend lists the identities (certificate + usable private key) in one keystore and finds one by a query. Built-in backends:
========== ================================ =====================================
name class keystore
========== ================================ =====================================
cng :class:CNGBackend Windows certificate stores (CNG/CAPI)
pkcs11 :class:PKCS11Backend PKCS#11 tokens: smart cards, HSMs, TPMs
keychain :class:KeychainBackend the macOS Keychain, smart cards included
========== ================================ =====================================
Third-party backends register under the entry-point group
sslcontext.backends (name = "package.module:Class").
Backend
Bases: ABC
One keystore. Constructing it does no I/O; :meth:close releases it.
Subclasses implement :meth:identities; querying is shared. A backend is
a context manager, and identities it returned stay usable after it is
closed.
close()
Release what the backend holds open. Harmless to call twice.
Source code in src/sslcontext/backends/__init__.py
65 66 | |
identities()
abstractmethod
Every identity in the keystore whose private key can be used.
Raises :class:~sslcontext.exceptions.KeystoreError when the
keystore cannot be read.
Source code in src/sslcontext/backends/__init__.py
68 69 70 71 72 73 74 | |
find_identities(*, thumbprint=None, subject=None, issuer=None, label=None, valid=True)
The identities matching every criterion given, newest expiry first.
thumbprint is the certificate's SHA-1 or SHA-256 in hex (case,
spaces and colons ignored). subject and issuer match a
case-insensitive substring of the RFC 4514 name. label matches
the keystore's own name for the entry exactly, ignoring case.
valid keeps only certificates valid now.
Source code in src/sslcontext/backends/__init__.py
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | |
find_identity(**query)
The best match for :meth:find_identities (**query).
Several matches resolve to the one that expires last, so a renewed
certificate wins over the one it replaces. Raises
:class:~sslcontext.exceptions.IdentityNotFoundError when nothing
matches.
Source code in src/sslcontext/backends/__init__.py
112 113 114 115 116 117 118 119 120 121 122 123 124 | |
register_backend(name, backend)
Register backend (a class, or "module:Class") under name.
Names are lower case; registering a taken name raises ValueError.
Source code in src/sslcontext/backends/__init__.py
131 132 133 134 135 136 137 138 139 140 141 | |
names()
Every registered backend name, built-in and third-party.
Source code in src/sslcontext/backends/__init__.py
162 163 164 165 | |
get(name)
The backend class registered as name.
An unknown name raises ValueError naming the registered ones.
Source code in src/sslcontext/backends/__init__.py
168 169 170 171 172 173 174 175 176 177 178 179 180 | |
Issuing certificates
A small certificate authority: create or load one, issue server certificates.
Keys and certificates are made by the interpreter's own OpenSSL, the one the
ssl module uses, so no third-party package is needed and the result works
on OpenSSL 1.1.1 and 3.x alike. The CA's private key is held in memory;
:meth:CertificateAuthority.private_key_pem exports it (optionally
encrypted) for the caller to store.
Meant for local use: test servers, and proxies that terminate TLS for
clients told to trust the CA. Restrict such a CA with permitted= (X.509
name constraints) so that, if its key leaks, it cannot vouch for other sites.
IssuedCertificate(certificate, key, chain=b'')
dataclass
A leaf certificate and its key, as PEM.
chain holds the issuing CA's certificate. :meth:load_into installs
all of it into a context.
info
property
The decoded leaf certificate.
CertificateAuthority(certificate, key, password=None)
A CA whose certificate and private key are held in memory.
Construct from PEM (certificate and key; password decrypts an
encrypted key) or with :meth:create. Raises CredentialError for
malformed PEM or a key that is not the certificate's.
Source code in src/sslcontext/issuing.py
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 | |
certificate = _bio_bytes(lib, lib.PEM_write_bio_X509, self._x509)
instance-attribute
The CA certificate, PEM: what clients must trust.
create(common_name, *, permitted=(), days=3650, key_type='ec')
classmethod
A new self-signed CA.
permitted names what it may vouch for, as critical X.509 name
constraints: DNS names (corp.example covers its subdomains;
*.corp.example and .corp.example mean the same) and IP
networks (10.0.0.0/8). Empty means unconstrained. key_type
is "ec" (P-256) or "rsa" (2048-bit). ValueError for a
name that cannot be a constraint.
Source code in src/sslcontext/issuing.py
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 | |
private_key_pem(password=None)
The CA key as PKCS#8 PEM, AES-256 encrypted when password is given.
Source code in src/sslcontext/issuing.py
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 | |
issue(names, *, days=30, key_type='ec', common_name=None)
A server certificate for names (DNS names and IP addresses).
The leaf carries them as subject alternative names, serverAuth and
clientAuth usage, and an authority key identifier, so strict X.509
verification (the default from Python 3.13) accepts it. A fresh key
each time. ValueError for an empty names.
Source code in src/sslcontext/issuing.py
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 | |
server_context(names, **options)
A server context presenting a fresh certificate for names.
options go to :func:sslcontext.create_context (purpose is
"server").
Source code in src/sslcontext/issuing.py
413 414 415 416 417 418 419 420 421 | |
Test helpers
Test helpers: a :class:Signer over an in-memory key.
:class:SoftwareSigner holds an ordinary private key and signs with
OpenSSL, through the same :class:Signer contract a keystore backend
implements. It exercises the whole keystore path without a keystore, and it
is the reference for what a backend's sign must return.
SoftwareSigner(key, password=None)
Signs with a PEM or DER private key held in memory.
calls records (hash, padding, salt_length) for every signature, so
a test can see what the TLS stack asked for.
Source code in src/sslcontext/testing.py
42 43 44 45 46 | |
software_identity(certificate, key, password=None)
An :class:Identity for a PEM certificate (+ chain) and an in-memory key.
Source code in src/sslcontext/testing.py
141 142 143 144 145 146 147 148 149 150 151 152 153 154 | |