Verify certificates using native system trust stores
npx @tessl/cli install tessl/pypi-truststore@0.10.0A Python library that exposes native system certificate stores (trust stores) through an ssl.SSLContext-like API. This eliminates the need for applications to rely on certifi as a root certificate store, enabling automatic certificate updates, intermediate certificate fetching, and certificate revocation list (CRL) checking.
pip install truststoreimport truststoreFor type hints when using SSLContext:
import ssl
import os
import typing
import truststore
from typing_extensions import BufferWarning: inject_into_ssl() must not be used by libraries or packages as it will cause issues on import time when integrated with other libraries. Libraries should use truststore.SSLContext directly.
import truststore
import requests
import urllib3
import aiohttp
# Inject truststore into the ssl module
truststore.inject_into_ssl()
# Now all libraries automatically use system trust stores
resp = requests.get("https://example.com")
# Works with urllib3
http = urllib3.PoolManager()
resp = http.request("GET", "https://example.com")
# Works with aiohttp
async with aiohttp.ClientSession() as session:
resp = await session.get("https://example.com")
# Restore original ssl.SSLContext when done
truststore.extract_from_ssl()import ssl
import truststore
import urllib3
# Create a truststore SSLContext instance
ctx = truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
# Use it anywhere you'd use an ssl.SSLContext
http = urllib3.PoolManager(ssl_context=ctx)
resp = http.request("GET", "https://example.com")
# Configure SSL context properties as needed
ctx.check_hostname = True
ctx.verify_mode = ssl.CERT_REQUIREDCreates an SSLContext that uses the native system certificate store for certificate verification.
class SSLContext:
def __init__(self, protocol: int = None) -> None:
"""
Initialize an SSLContext using native system trust stores.
Parameters:
- protocol: SSL protocol version (e.g., ssl.PROTOCOL_TLS_CLIENT)
"""def wrap_socket(
self,
sock: socket.socket,
server_side: bool = False,
do_handshake_on_connect: bool = True,
suppress_ragged_eofs: bool = True,
server_hostname: str | None = None,
session: ssl.SSLSession | None = None,
) -> ssl.SSLSocket:
"""
Wrap a socket with SSL using system trust store for verification.
Parameters:
- sock: The socket to wrap
- server_side: Whether this is a server-side connection
- do_handshake_on_connect: Whether to perform handshake immediately
- suppress_ragged_eofs: Whether to suppress ragged EOF errors
- server_hostname: Expected hostname for certificate verification
- session: SSL session to reuse
Returns:
SSL-wrapped socket
"""def wrap_bio(
self,
incoming: ssl.MemoryBIO,
outgoing: ssl.MemoryBIO,
server_side: bool = False,
server_hostname: str | None = None,
session: ssl.SSLSession | None = None,
) -> ssl.SSLObject:
"""
Wrap BIO objects with SSL using system trust store.
Parameters:
- incoming: Incoming data BIO
- outgoing: Outgoing data BIO
- server_side: Whether this is a server-side connection
- server_hostname: Expected hostname for certificate verification
- session: SSL session to reuse
Returns:
SSL object for the wrapped BIOs
"""def load_verify_locations(
self,
cafile: str | bytes | os.PathLike[str] | os.PathLike[bytes] | None = None,
capath: str | bytes | os.PathLike[str] | os.PathLike[bytes] | None = None,
cadata: typing.Union[str, Buffer, None] = None,
) -> None:
"""
Load additional certificate verification locations.
Parameters:
- cafile: Path to certificate authority file
- capath: Path to directory containing CA certificates
- cadata: Certificate authority data as string or buffer-like object
"""def load_cert_chain(
self,
certfile: str | bytes | os.PathLike[str] | os.PathLike[bytes],
keyfile: str | bytes | os.PathLike[str] | os.PathLike[bytes] | None = None,
password: str | bytes | callable | None = None,
) -> None:
"""
Load client certificate chain.
Parameters:
- certfile: Path to certificate file
- keyfile: Path to private key file (optional if included in certfile)
- password: Password for encrypted key file
"""def load_default_certs(self, purpose: ssl.Purpose = ssl.Purpose.SERVER_AUTH) -> None:
"""
Load default certificates for the specified purpose.
Parameters:
- purpose: Certificate purpose (SERVER_AUTH or CLIENT_AUTH)
"""def set_default_verify_paths(self) -> None:
"""Set default certificate verification paths."""def set_alpn_protocols(self, alpn_protocols: typing.Iterable[str]) -> None:
"""
Set Application-Layer Protocol Negotiation protocols.
Parameters:
- alpn_protocols: Iterable of protocol names
"""def set_npn_protocols(self, npn_protocols: typing.Iterable[str]) -> None:
"""
Set Next Protocol Negotiation protocols.
Parameters:
- npn_protocols: Iterable of protocol names
"""def set_ciphers(self, cipherlist: str) -> None:
"""
Set available ciphers.
Parameters:
- cipherlist: OpenSSL cipher specification string
"""def get_ciphers(self) -> typing.Any:
"""
Get list of available ciphers.
Returns:
List of cipher dictionaries with details
"""def session_stats(self) -> dict[str, int]:
"""
Get SSL session statistics.
Returns:
Dictionary of session statistics
"""def cert_store_stats(self) -> dict[str, int]:
"""
Get certificate store statistics.
Raises:
NotImplementedError: This method is not implemented
"""def get_ca_certs(self, binary_form: bool = False) -> list[typing.Any] | list[bytes]:
"""
Get CA certificates from the store.
Parameters:
- binary_form: Whether to return certificates in binary DER format
Returns:
List of certificate dictionaries or binary data
Raises:
NotImplementedError: This method is not implemented
"""# Boolean properties
check_hostname: bool # Enable/disable hostname checking
hostname_checks_common_name: bool # Check common name in hostname verification
post_handshake_auth: bool # Enable post-handshake authentication
# String properties
keylog_filename: str # Filename for SSL key logging
# Enum properties
maximum_version: ssl.TLSVersion # Maximum TLS version
minimum_version: ssl.TLSVersion # Minimum TLS version
options: ssl.Options # SSL options
verify_flags: ssl.VerifyFlags # Certificate verification flags
verify_mode: ssl.VerifyMode # Certificate verification mode
# Read-only properties
protocol: ssl._SSLMethod # SSL protocol (read-only)
security_level: int # Security level (read-only)Replaces the ssl.SSLContext class globally to use system trust stores automatically.
def inject_into_ssl() -> None:
"""
Inject truststore.SSLContext into the ssl module by replacing ssl.SSLContext.
Also patches urllib3 and requests to use truststore automatically.
Warning: Only use in applications, never in libraries or packages.
"""Restores the original ssl.SSLContext class, undoing the effects of inject_into_ssl().
def extract_from_ssl() -> None:
"""
Restore the ssl.SSLContext class to its original state.
Undoes the effects of inject_into_ssl().
"""The following standard ssl.SSLContext methods are not available in truststore.SSLContext:
load_dh_params() - DH parameter loading not supportedset_ecdh_curve() - ECDH curve configuration not supportedset_servername_callback() - SNI callback setting not supportedsni_callback property - SNI callback property not availablenum_tickets property - TLS session ticket configuration not availablesslobject_class and sslsocket_class properties - Internal SSL object classes not directly accessible_ctx_lock) to ensure safe concurrent usage_windows.py, _macos.py, _openssl.py)get_unverified_chain() APIThe SSLContext behaves like the standard ssl.SSLContext with additional certificate verification using system trust stores. Standard SSL exceptions (ssl.SSLError, ssl.CertificateError, etc.) are raised for certificate verification failures, with platform-specific error messages providing details about trust store validation failures.