Verify certificates using native system trust stores
npx @tessl/cli install tessl/pypi-truststore@0.10.00
# Truststore
1
2
A 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.
3
4
## Package Information
5
6
- **Package Name**: truststore
7
- **Version**: 0.10.4
8
- **Language**: Python
9
- **Installation**: `pip install truststore`
10
- **Requirements**: Python 3.10+
11
- **Platforms**: macOS 10.8+ (Security framework), Windows (CryptoAPI), Linux (OpenSSL)
12
13
## Core Imports
14
15
```python
16
import truststore
17
```
18
19
For type hints when using SSLContext:
20
21
```python
22
import ssl
23
import os
24
import typing
25
import truststore
26
from typing_extensions import Buffer
27
```
28
29
## Basic Usage
30
31
### Global SSL Injection (Applications Only)
32
33
**Warning**: `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.
34
35
```python
36
import truststore
37
import requests
38
import urllib3
39
import aiohttp
40
41
# Inject truststore into the ssl module
42
truststore.inject_into_ssl()
43
44
# Now all libraries automatically use system trust stores
45
resp = requests.get("https://example.com")
46
47
# Works with urllib3
48
http = urllib3.PoolManager()
49
resp = http.request("GET", "https://example.com")
50
51
# Works with aiohttp
52
async with aiohttp.ClientSession() as session:
53
resp = await session.get("https://example.com")
54
55
# Restore original ssl.SSLContext when done
56
truststore.extract_from_ssl()
57
```
58
59
### Direct SSLContext Usage (Libraries and Fine-grained Control)
60
61
```python
62
import ssl
63
import truststore
64
import urllib3
65
66
# Create a truststore SSLContext instance
67
ctx = truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
68
69
# Use it anywhere you'd use an ssl.SSLContext
70
http = urllib3.PoolManager(ssl_context=ctx)
71
resp = http.request("GET", "https://example.com")
72
73
# Configure SSL context properties as needed
74
ctx.check_hostname = True
75
ctx.verify_mode = ssl.CERT_REQUIRED
76
```
77
78
## Capabilities
79
80
### SSL Context Creation
81
82
Creates an SSLContext that uses the native system certificate store for certificate verification.
83
84
```python { .api }
85
class SSLContext:
86
def __init__(self, protocol: int = None) -> None:
87
"""
88
Initialize an SSLContext using native system trust stores.
89
90
Parameters:
91
- protocol: SSL protocol version (e.g., ssl.PROTOCOL_TLS_CLIENT)
92
"""
93
```
94
95
#### Socket and BIO Wrapping
96
97
```python { .api }
98
def wrap_socket(
99
self,
100
sock: socket.socket,
101
server_side: bool = False,
102
do_handshake_on_connect: bool = True,
103
suppress_ragged_eofs: bool = True,
104
server_hostname: str | None = None,
105
session: ssl.SSLSession | None = None,
106
) -> ssl.SSLSocket:
107
"""
108
Wrap a socket with SSL using system trust store for verification.
109
110
Parameters:
111
- sock: The socket to wrap
112
- server_side: Whether this is a server-side connection
113
- do_handshake_on_connect: Whether to perform handshake immediately
114
- suppress_ragged_eofs: Whether to suppress ragged EOF errors
115
- server_hostname: Expected hostname for certificate verification
116
- session: SSL session to reuse
117
118
Returns:
119
SSL-wrapped socket
120
"""
121
```
122
123
```python { .api }
124
def wrap_bio(
125
self,
126
incoming: ssl.MemoryBIO,
127
outgoing: ssl.MemoryBIO,
128
server_side: bool = False,
129
server_hostname: str | None = None,
130
session: ssl.SSLSession | None = None,
131
) -> ssl.SSLObject:
132
"""
133
Wrap BIO objects with SSL using system trust store.
134
135
Parameters:
136
- incoming: Incoming data BIO
137
- outgoing: Outgoing data BIO
138
- server_side: Whether this is a server-side connection
139
- server_hostname: Expected hostname for certificate verification
140
- session: SSL session to reuse
141
142
Returns:
143
SSL object for the wrapped BIOs
144
"""
145
```
146
147
#### Certificate Management
148
149
```python { .api }
150
def load_verify_locations(
151
self,
152
cafile: str | bytes | os.PathLike[str] | os.PathLike[bytes] | None = None,
153
capath: str | bytes | os.PathLike[str] | os.PathLike[bytes] | None = None,
154
cadata: typing.Union[str, Buffer, None] = None,
155
) -> None:
156
"""
157
Load additional certificate verification locations.
158
159
Parameters:
160
- cafile: Path to certificate authority file
161
- capath: Path to directory containing CA certificates
162
- cadata: Certificate authority data as string or buffer-like object
163
"""
164
```
165
166
```python { .api }
167
def load_cert_chain(
168
self,
169
certfile: str | bytes | os.PathLike[str] | os.PathLike[bytes],
170
keyfile: str | bytes | os.PathLike[str] | os.PathLike[bytes] | None = None,
171
password: str | bytes | callable | None = None,
172
) -> None:
173
"""
174
Load client certificate chain.
175
176
Parameters:
177
- certfile: Path to certificate file
178
- keyfile: Path to private key file (optional if included in certfile)
179
- password: Password for encrypted key file
180
"""
181
```
182
183
```python { .api }
184
def load_default_certs(self, purpose: ssl.Purpose = ssl.Purpose.SERVER_AUTH) -> None:
185
"""
186
Load default certificates for the specified purpose.
187
188
Parameters:
189
- purpose: Certificate purpose (SERVER_AUTH or CLIENT_AUTH)
190
"""
191
```
192
193
```python { .api }
194
def set_default_verify_paths(self) -> None:
195
"""Set default certificate verification paths."""
196
```
197
198
#### Protocol and Cipher Configuration
199
200
```python { .api }
201
def set_alpn_protocols(self, alpn_protocols: typing.Iterable[str]) -> None:
202
"""
203
Set Application-Layer Protocol Negotiation protocols.
204
205
Parameters:
206
- alpn_protocols: Iterable of protocol names
207
"""
208
```
209
210
```python { .api }
211
def set_npn_protocols(self, npn_protocols: typing.Iterable[str]) -> None:
212
"""
213
Set Next Protocol Negotiation protocols.
214
215
Parameters:
216
- npn_protocols: Iterable of protocol names
217
"""
218
```
219
220
```python { .api }
221
def set_ciphers(self, cipherlist: str) -> None:
222
"""
223
Set available ciphers.
224
225
Parameters:
226
- cipherlist: OpenSSL cipher specification string
227
"""
228
```
229
230
```python { .api }
231
def get_ciphers(self) -> typing.Any:
232
"""
233
Get list of available ciphers.
234
235
Returns:
236
List of cipher dictionaries with details
237
"""
238
```
239
240
#### Statistics and Information
241
242
```python { .api }
243
def session_stats(self) -> dict[str, int]:
244
"""
245
Get SSL session statistics.
246
247
Returns:
248
Dictionary of session statistics
249
"""
250
```
251
252
```python { .api }
253
def cert_store_stats(self) -> dict[str, int]:
254
"""
255
Get certificate store statistics.
256
257
Raises:
258
NotImplementedError: This method is not implemented
259
"""
260
```
261
262
```python { .api }
263
def get_ca_certs(self, binary_form: bool = False) -> list[typing.Any] | list[bytes]:
264
"""
265
Get CA certificates from the store.
266
267
Parameters:
268
- binary_form: Whether to return certificates in binary DER format
269
270
Returns:
271
List of certificate dictionaries or binary data
272
273
Raises:
274
NotImplementedError: This method is not implemented
275
"""
276
```
277
278
#### SSL Context Properties
279
280
```python { .api }
281
# Boolean properties
282
check_hostname: bool # Enable/disable hostname checking
283
hostname_checks_common_name: bool # Check common name in hostname verification
284
post_handshake_auth: bool # Enable post-handshake authentication
285
286
# String properties
287
keylog_filename: str # Filename for SSL key logging
288
289
# Enum properties
290
maximum_version: ssl.TLSVersion # Maximum TLS version
291
minimum_version: ssl.TLSVersion # Minimum TLS version
292
options: ssl.Options # SSL options
293
verify_flags: ssl.VerifyFlags # Certificate verification flags
294
verify_mode: ssl.VerifyMode # Certificate verification mode
295
296
# Read-only properties
297
protocol: ssl._SSLMethod # SSL protocol (read-only)
298
security_level: int # Security level (read-only)
299
```
300
301
### Global SSL Injection
302
303
Replaces the ssl.SSLContext class globally to use system trust stores automatically.
304
305
```python { .api }
306
def inject_into_ssl() -> None:
307
"""
308
Inject truststore.SSLContext into the ssl module by replacing ssl.SSLContext.
309
Also patches urllib3 and requests to use truststore automatically.
310
311
Warning: Only use in applications, never in libraries or packages.
312
"""
313
```
314
315
### SSL Extraction
316
317
Restores the original ssl.SSLContext class, undoing the effects of inject_into_ssl().
318
319
```python { .api }
320
def extract_from_ssl() -> None:
321
"""
322
Restore the ssl.SSLContext class to its original state.
323
Undoes the effects of inject_into_ssl().
324
"""
325
```
326
327
## Key Features
328
329
- **Automatic Certificate Updates**: Certificates are updated as CAs are created/removed by the system
330
- **Intermediate Certificate Fetching**: Missing intermediate certificates are automatically retrieved
331
- **Certificate Revocation Checking**: Checks against certificate revocation lists (CRLs) to prevent MITM attacks
332
- **System-managed**: Certificates are managed per-system by operations/IT teams rather than per-application
333
- **Cross-platform**: Works on macOS (Security framework), Windows (CryptoAPI), and Linux (OpenSSL)
334
- **Library Integration**: Compatible with urllib3, requests, aiohttp, and other SSL-using libraries
335
- **Thread-safe**: Internal locking ensures safe concurrent usage
336
337
## Limitations
338
339
The following standard `ssl.SSLContext` methods are **not available** in `truststore.SSLContext`:
340
341
- `load_dh_params()` - DH parameter loading not supported
342
- `set_ecdh_curve()` - ECDH curve configuration not supported
343
- `set_servername_callback()` - SNI callback setting not supported
344
- `sni_callback` property - SNI callback property not available
345
- `num_tickets` property - TLS session ticket configuration not available
346
- `sslobject_class` and `sslsocket_class` properties - Internal SSL object classes not directly accessible
347
348
## Implementation Details
349
350
- **Thread Safety**: All operations are protected by internal locking (`_ctx_lock`) to ensure safe concurrent usage
351
- **Platform Verification**: Uses platform-specific certificate verification implementations (`_windows.py`, `_macos.py`, `_openssl.py`)
352
- **Certificate Chain Handling**: Automatically extracts and verifies full certificate chains using `get_unverified_chain()` API
353
354
## Error Handling
355
356
The 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.