cert-utils 1.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. cert_utils/__init__.py +8 -0
  2. cert_utils/compat/__init__.py +0 -0
  3. cert_utils/compat/cryptography.py +172 -0
  4. cert_utils/compat/openssl.py +860 -0
  5. cert_utils/compat/pyopenssl.py +207 -0
  6. cert_utils/compat/signatures.py +114 -0
  7. cert_utils/conditionals.py +121 -0
  8. cert_utils/convert.py +307 -0
  9. cert_utils/core.py +3075 -0
  10. cert_utils/errors.py +54 -0
  11. cert_utils/letsencrypt-certs/deprecated/e5-cross.pem +26 -0
  12. cert_utils/letsencrypt-certs/deprecated/e5.pem +17 -0
  13. cert_utils/letsencrypt-certs/deprecated/e6-cross.pem +26 -0
  14. cert_utils/letsencrypt-certs/deprecated/e6.pem +17 -0
  15. cert_utils/letsencrypt-certs/deprecated/e7-cross.pem +26 -0
  16. cert_utils/letsencrypt-certs/deprecated/e7.pem +17 -0
  17. cert_utils/letsencrypt-certs/deprecated/e8-cross.pem +26 -0
  18. cert_utils/letsencrypt-certs/deprecated/e8.pem +17 -0
  19. cert_utils/letsencrypt-certs/deprecated/e9-cross.pem +26 -0
  20. cert_utils/letsencrypt-certs/deprecated/e9.pem +17 -0
  21. cert_utils/letsencrypt-certs/deprecated/fakeleintermediatex1.pem +28 -0
  22. cert_utils/letsencrypt-certs/deprecated/fakelerootx1.pem +29 -0
  23. cert_utils/letsencrypt-certs/deprecated/isrg-root-ocsp-x1.pem +28 -0
  24. cert_utils/letsencrypt-certs/deprecated/isrg-root-x1-cross-signed.pem +31 -0
  25. cert_utils/letsencrypt-certs/deprecated/isrg-root-x2-cross-signed.pem +26 -0
  26. cert_utils/letsencrypt-certs/deprecated/lets-encrypt-e1.pem +17 -0
  27. cert_utils/letsencrypt-certs/deprecated/lets-encrypt-e2.pem +17 -0
  28. cert_utils/letsencrypt-certs/deprecated/lets-encrypt-r3-cross-signed.pem +26 -0
  29. cert_utils/letsencrypt-certs/deprecated/lets-encrypt-r3.pem +30 -0
  30. cert_utils/letsencrypt-certs/deprecated/lets-encrypt-r4-cross-signed.pem +26 -0
  31. cert_utils/letsencrypt-certs/deprecated/lets-encrypt-r4.pem +30 -0
  32. cert_utils/letsencrypt-certs/deprecated/lets-encrypt-x1-cross-signed.pem +27 -0
  33. cert_utils/letsencrypt-certs/deprecated/lets-encrypt-x2-cross-signed.pem +27 -0
  34. cert_utils/letsencrypt-certs/deprecated/lets-encrypt-x3-cross-signed.pem +27 -0
  35. cert_utils/letsencrypt-certs/deprecated/lets-encrypt-x4-cross-signed.pem +27 -0
  36. cert_utils/letsencrypt-certs/deprecated/letsencrypt-stg-root-x2-signed-by-x1.pem +27 -0
  37. cert_utils/letsencrypt-certs/deprecated/letsencryptauthorityx1.pem +32 -0
  38. cert_utils/letsencrypt-certs/deprecated/letsencryptauthorityx2.pem +32 -0
  39. cert_utils/letsencrypt-certs/deprecated/letsencryptauthorityx3.pem +32 -0
  40. cert_utils/letsencrypt-certs/deprecated/letsencryptauthorityx4.pem +32 -0
  41. cert_utils/letsencrypt-certs/deprecated/r10.pem +29 -0
  42. cert_utils/letsencrypt-certs/deprecated/r11.pem +29 -0
  43. cert_utils/letsencrypt-certs/deprecated/r12.pem +29 -0
  44. cert_utils/letsencrypt-certs/deprecated/r13.pem +29 -0
  45. cert_utils/letsencrypt-certs/deprecated/r14.pem +29 -0
  46. cert_utils/letsencrypt-certs/deprecated/trustid-x3-root.p7c +0 -0
  47. cert_utils/letsencrypt-certs/deprecated/trustid-x3-root.pem +20 -0
  48. cert_utils/letsencrypt-certs/int-ye1.pem +16 -0
  49. cert_utils/letsencrypt-certs/int-ye2.pem +16 -0
  50. cert_utils/letsencrypt-certs/int-ye3.pem +16 -0
  51. cert_utils/letsencrypt-certs/int-yr1.pem +28 -0
  52. cert_utils/letsencrypt-certs/int-yr2.pem +28 -0
  53. cert_utils/letsencrypt-certs/int-yr3.pem +28 -0
  54. cert_utils/letsencrypt-certs/isrg-root-x2.pem +14 -0
  55. cert_utils/letsencrypt-certs/isrgrootx1.pem +31 -0
  56. cert_utils/letsencrypt-certs/isrgrootx1.pkix +0 -0
  57. cert_utils/letsencrypt-certs/letsencrypt-stg-root-x1.pem +32 -0
  58. cert_utils/letsencrypt-certs/letsencrypt-stg-root-x2.pem +15 -0
  59. cert_utils/letsencrypt-certs/root-x2-by-x1.pem +26 -0
  60. cert_utils/letsencrypt-certs/root-ye-by-x2.pem +17 -0
  61. cert_utils/letsencrypt-certs/root-ye.pem +12 -0
  62. cert_utils/letsencrypt-certs/root-yr-by-x1.pem +34 -0
  63. cert_utils/letsencrypt-certs/root-yr.pem +30 -0
  64. cert_utils/letsencrypt_info/__init__.py +6 -0
  65. cert_utils/letsencrypt_info/certificates.py +1074 -0
  66. cert_utils/letsencrypt_info/rate_limits.py +414 -0
  67. cert_utils/letsencrypt_info/types.py +120 -0
  68. cert_utils/model.py +181 -0
  69. cert_utils/network.py +28 -0
  70. cert_utils/py.typed +0 -0
  71. cert_utils/scripts/__init__.py +0 -0
  72. cert_utils/scripts/cert_info.py +332 -0
  73. cert_utils/utils.py +388 -0
  74. cert_utils-1.2.0.dist-info/METADATA +259 -0
  75. cert_utils-1.2.0.dist-info/RECORD +79 -0
  76. cert_utils-1.2.0.dist-info/WHEEL +5 -0
  77. cert_utils-1.2.0.dist-info/entry_points.txt +2 -0
  78. cert_utils-1.2.0.dist-info/licenses/LICENSE.txt +224 -0
  79. cert_utils-1.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1074 @@
1
+ """
2
+ This file contains the following:
3
+
4
+ * Information on the LetsEncrypt Trust Chain
5
+ * A routine to load the LetsEncrypt Certificates into Python
6
+
7
+ Because this loads Certificates into memory for some operations, it should
8
+ generally not be imported.
9
+ """
10
+
11
+ # stdlib
12
+ import copy
13
+ import os
14
+ from typing import Any
15
+ from typing import Dict
16
+ from typing import Optional
17
+
18
+ # pypi
19
+ import requests
20
+
21
+ # localapp
22
+ from .types import CERT_CA_PAYLOAD
23
+ from ..network import get_timeout
24
+ from ..network import Timeout
25
+ from ..utils import cleanup_pem_text
26
+ from ..utils import md5_text
27
+
28
+ # ==============================================================================
29
+
30
+
31
+ # certificates are published online
32
+ # https://letsencrypt.org/certificates/
33
+ # last checked: 2026.10.28 (website checkout bb7e7238; certificates page 2026-07-08)
34
+
35
+ # this info is checked for compliance with
36
+ # * tests.test_unit.UnitTest_LetsEncrypt_Data
37
+
38
+
39
+ CERT_CAS_VERSION = 5 # update when the information below changes
40
+ """
41
+ format details:
42
+
43
+ the KEY in the dictionary is a unique string
44
+
45
+ the payload can have one of these two values, which reference another key:
46
+ "alternates": ["isrg_root_x2_cross"],
47
+ "alternate_of": "isrg_root_x2",
48
+
49
+ Special Values
50
+ ".enddate": the args to datetime.datetime()
51
+
52
+ Compatibility Info
53
+ via https://letsencrypt.org/docs/certificate-compatibility/
54
+ Last updated: Jan 21, 2021
55
+
56
+ ["cert.fingerprints"]["sha1"] = `openssl x509 -fingerprint -sha1 -noout -in isrg-root-x2.pem`
57
+
58
+ """
59
+
60
+ CERT_CAS_DEPRECATED: Dict[str, CERT_CA_PAYLOAD] = {
61
+ "trustid_root_x3": {
62
+ "display_name": "DST Root CA X3",
63
+ "url_pem": "https://letsencrypt.org/certs/trustid-x3-root.pem",
64
+ "is_trusted_root": True,
65
+ "is_self_signed": True,
66
+ "signed_by": "trustid_root_x3",
67
+ "is_active": False,
68
+ "key_technology": "RSA",
69
+ "cert.fingerprints": {
70
+ "sha1": "DAC9024F54D8F6DF94935FB1732638CA6AD77C13",
71
+ "sha256": "0687260331A72403D909F105E69BCF0D32E1BD2493FFC6D9206D11BCD6770739",
72
+ },
73
+ ".enddate": (2021, 9, 30, 14, 1, 15),
74
+ "compatibility": {
75
+ "Windows": (">= XP SP3", None, None),
76
+ "macOS": ("(most versions)", None, None),
77
+ "iOS": ("(most versions)", None, None),
78
+ "Android": (">= v2.3.6", None, None),
79
+ "Mozilla Firefox": (">= v2.0", None, None),
80
+ "Ubuntu": (">= precise / 12.04", None, None),
81
+ "Debian": (">= squeee / 6", None, None),
82
+ "Java 8": (">= 8u101", None, None),
83
+ "Java 7": (">= 7u111", None, None),
84
+ "NSS": (">= v3.11.9", None, None),
85
+ "Amazon FireOS (Silk Browser)": ("?", None, None),
86
+ "Cyanogen": ("> v10", None, None),
87
+ "Jolla Sailfish OS": ("> v1.1.2.16", None, None),
88
+ "Kindle": ("> v3.4.1", None, None),
89
+ "Blackberry": (">= 10.3.3", None, None),
90
+ "PS4 game console": ("with firmware >= 5.00", None, None),
91
+ },
92
+ "is_retired": True,
93
+ },
94
+ "isrg_root_x1_cross": {
95
+ "display_name": "ISRG Root X1 (IdenTrust cross-signed)",
96
+ "url_pem": "https://letsencrypt.org/certs/isrg-root-x1-cross-signed.pem",
97
+ "is_trusted_root": False,
98
+ "is_active": False,
99
+ "is_retired": True,
100
+ "key_technology": "RSA",
101
+ "signed_by": "trustid_root_x3",
102
+ "alternate_of": "isrg_root_x1",
103
+ "cert.fingerprints": {
104
+ "sha1": "933C6DDEE95C9C41A40F9F50493D82BE03AD87BF",
105
+ "sha256": "6D99FB265EB1C5B3744765FCBC648F3CD8E1BFFAFDC4C2F99B9D47CF7FF1C24F",
106
+ },
107
+ ".enddate": (2024, 9, 30, 18, 14, 3),
108
+ "is_self_signed": False,
109
+ },
110
+ "letsencrypt_ocsp_root_x1": {
111
+ "display_name": "Let's Encrypt OSCP Root X1",
112
+ "url_pem": "https://letsencrypt.org/certs/isrg-root-ocsp-x1.pem",
113
+ "is_active": False,
114
+ "is_retired": True,
115
+ "key_technology": "RSA",
116
+ "signed_by": "isrg_root_x1",
117
+ "cert.fingerprints": {
118
+ "sha1": "7D2671CBB2F689F0E88389DE2880FA1BD0857582",
119
+ "sha256": "F21BC92040EC5DBAA820418A24936628FF87C177E1A5D8AB41FA7EE1FF812642",
120
+ },
121
+ ".enddate": (2025, 6, 10, 13, 4, 11),
122
+ "is_self_signed": False,
123
+ },
124
+ "letsencrypt_intermediate_x1": {
125
+ "display_name": "Let's Encrypt Authority X1",
126
+ "url_pem": "https://letsencrypt.org/certs/letsencryptauthorityx1.pem",
127
+ "is_active": False,
128
+ "is_retired": True,
129
+ "key_technology": "RSA",
130
+ "signed_by": "isrg_root_x1",
131
+ "alternates": ["letsencrypt_intermediate_x1_cross"],
132
+ "letsencrypt_serial": "x1",
133
+ "cert.fingerprints": {
134
+ "sha1": "E045A5A959F42780FA5BD7623512AF276CF42F20",
135
+ "sha256": "BDEE0D7C8F9C278F14EA9B6A4F90ED665A9F56DB0A56B1CDDA6765912F398A5E",
136
+ },
137
+ ".enddate": (2020, 6, 4, 12, 0, 20),
138
+ "is_self_signed": False,
139
+ },
140
+ "letsencrypt_intermediate_x1_cross": {
141
+ "display_name": "Let's Encrypt Authority X1 (IdenTrust cross-signed)",
142
+ "url_pem": "https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem",
143
+ "is_active": False,
144
+ "is_retired": True,
145
+ "key_technology": "RSA",
146
+ "signed_by": "trustid_root_x3",
147
+ "alternate_of": "letsencrypt_intermediate_x1",
148
+ "letsencrypt_serial": "x1",
149
+ "cert.fingerprints": {
150
+ "sha1": "3EAE91937EC85D74483FF4B77B07B43E2AF36BF4",
151
+ "sha256": "7FDCE3BF4103C2684B3ADBB5792884BD45C75094C217788863950346F79C90A3",
152
+ },
153
+ ".enddate": (2020, 10, 19, 22, 33, 36),
154
+ "is_self_signed": False,
155
+ },
156
+ "letsencrypt_intermediate_x2": {
157
+ "display_name": "Let's Encrypt Authority X2",
158
+ "url_pem": "https://letsencrypt.org/certs/letsencryptauthorityx2.pem",
159
+ "is_active": False,
160
+ "is_retired": True,
161
+ "key_technology": "RSA",
162
+ "signed_by": "isrg_root_x1",
163
+ "alternates": ["letsencrypt_intermediate_x2_cross"],
164
+ "letsencrypt_serial": "x2",
165
+ "cert.fingerprints": {
166
+ "sha1": "3A7A7D70C08997BC33161744A5B7C24AD8F67B1B",
167
+ "sha256": "E4EB54A7FFA552EF64D8E1AE338B69BE909C29E6AF57170A2F6F44DF225E5A14",
168
+ },
169
+ ".enddate": (2020, 6, 4, 12, 0, 31),
170
+ "is_self_signed": False,
171
+ },
172
+ "letsencrypt_intermediate_x2_cross": {
173
+ "display_name": "Let's Encrypt Authority X2 (IdenTrust cross-signed)",
174
+ "url_pem": "https://letsencrypt.org/certs/lets-encrypt-x2-cross-signed.pem",
175
+ "is_active": False,
176
+ "is_retired": True,
177
+ "key_technology": "RSA",
178
+ "signed_by": "trustid_root_x3",
179
+ "alternate_of": "letsencrypt_intermediate_x2",
180
+ "letsencrypt_serial": "x2",
181
+ "cert.fingerprints": {
182
+ "sha1": "02007A05CED36899AA8A03A2CF307F1C0449FC31",
183
+ "sha256": "EC0C6CA496A67A13342FEC5221F68D4B3E53B1BC22F6E4BCCC9C68F0415CDEA4",
184
+ },
185
+ ".enddate": (2020, 10, 19, 22, 35, 1),
186
+ "is_self_signed": False,
187
+ },
188
+ "letsencrypt_intermediate_x3": {
189
+ "display_name": "Let's Encrypt Authority X3",
190
+ "url_pem": "https://letsencrypt.org/certs/letsencryptauthorityx3.pem",
191
+ "is_active": False,
192
+ "is_retired": True,
193
+ "key_technology": "RSA",
194
+ "signed_by": "isrg_root_x1",
195
+ "alternates": ["letsencrypt_intermediate_x3_cross"],
196
+ "letsencrypt_serial": "x3",
197
+ "cert.fingerprints": {
198
+ "sha1": "1B23675354FCAD90119D88075015EA17ADD527D8",
199
+ "sha256": "731D3D9CFAA061487A1D71445A42F67DF0AFCA2A6C2D2F98FF7B3CE112B1F568",
200
+ },
201
+ ".enddate": (2021, 10, 6, 15, 43, 55),
202
+ "is_self_signed": False,
203
+ },
204
+ "letsencrypt_intermediate_x3_cross": {
205
+ "display_name": "Let's Encrypt Authority X3 (IdenTrust cross-signed)",
206
+ "url_pem": "https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem",
207
+ "is_active": False,
208
+ "is_retired": True,
209
+ "key_technology": "RSA",
210
+ "signed_by": "trustid_root_x3",
211
+ "alternate_of": "letsencrypt_intermediate_x3",
212
+ "letsencrypt_serial": "x3",
213
+ "cert.fingerprints": {
214
+ "sha1": "E6A3B45B062D509B3382282D196EFE97D5956CCB",
215
+ "sha256": "25847D668EB4F04FDD40B12B6B0740C567DA7D024308EB6C2C96FE41D9DE218D",
216
+ },
217
+ ".enddate": (2021, 3, 17, 16, 40, 46),
218
+ "is_self_signed": False,
219
+ },
220
+ "letsencrypt_intermediate_x4": {
221
+ "display_name": "Let's Encrypt Authority X4",
222
+ "url_pem": "https://letsencrypt.org/certs/letsencryptauthorityx4.pem",
223
+ "is_active": False,
224
+ "is_retired": True,
225
+ "key_technology": "RSA",
226
+ "signed_by": "isrg_root_x1",
227
+ "alternates": ["letsencrypt_intermediate_x4_cross"],
228
+ "letsencrypt_serial": "x4",
229
+ "cert.fingerprints": {
230
+ "sha1": "77D6B59A84C605DF62B03ECB28DC168C50A93E98",
231
+ "sha256": "5DE9152BED31FA0515DD1FC746133F1327562EF72A84CF2D2403E748A604D0D4",
232
+ },
233
+ ".enddate": (2021, 10, 6, 15, 44, 34),
234
+ "is_self_signed": False,
235
+ },
236
+ "letsencrypt_intermediate_x4_cross": {
237
+ "display_name": "Let's Encrypt Authority X4 (IdenTrust cross-signed)",
238
+ "url_pem": "https://letsencrypt.org/certs/lets-encrypt-x4-cross-signed.pem",
239
+ "is_active": False,
240
+ "is_retired": True,
241
+ "key_technology": "RSA",
242
+ "signed_by": "trustid_root_x3",
243
+ "alternate_of": "letsencrypt_intermediate_x4",
244
+ "letsencrypt_serial": "x4",
245
+ "cert.fingerprints": {
246
+ "sha1": "C05E2471E589A57053F2747EE06A593C513E23A5",
247
+ "sha256": "A74B0C32B65B95FE2C4F8F098947A68B695033BED0B51DD8B984ECAE89571BB6",
248
+ },
249
+ ".enddate": (2021, 3, 17, 16, 41, 2),
250
+ "is_self_signed": False,
251
+ },
252
+ "letsencrypt_intermediate_r3": {
253
+ "display_name": "Let's Encrypt R3",
254
+ "url_pem": "https://letsencrypt.org/certs/lets-encrypt-r3.pem",
255
+ "is_active": False,
256
+ "is_retired": True,
257
+ "key_technology": "RSA",
258
+ "signed_by": "isrg_root_x1",
259
+ "alternates": ["letsencrypt_intermediate_r3_cross"],
260
+ "letsencrypt_serial": "r3",
261
+ "cert.fingerprints": {
262
+ "sha1": "A053375BFE84E8B748782C7CEE15827A6AF5A405",
263
+ "sha256": "67ADD1166B020AE61B8F5FC96813C04C2AA589960796865572A3C7E737613DFD",
264
+ },
265
+ ".enddate": (2025, 9, 15, 16, 0, 0),
266
+ "is_self_signed": False,
267
+ },
268
+ "letsencrypt_intermediate_r3_cross": {
269
+ "display_name": "Let's Encrypt R3 (IdenTrust cross-signed)",
270
+ "url_pem": "https://letsencrypt.org/certs/lets-encrypt-r3-cross-signed.pem",
271
+ "is_active": False,
272
+ "is_retired": True,
273
+ "key_technology": "RSA",
274
+ "signed_by": "trustid_root_x3",
275
+ "alternate_of": "letsencrypt_intermediate_r3",
276
+ "letsencrypt_serial": "r3",
277
+ "cert.fingerprints": {
278
+ "sha1": "48504E974C0DAC5B5CD476C8202274B24C8C7172",
279
+ "sha256": "730C1BDCD85F57CE5DC0BBA733E5F1BA5A925B2A771D640A26F7A454224DAD3B",
280
+ },
281
+ ".enddate": (2021, 9, 29, 19, 21, 40),
282
+ "is_self_signed": False,
283
+ },
284
+ "letsencrypt_intermediate_r4": {
285
+ "display_name": "Let's Encrypt R4",
286
+ "url_pem": "https://letsencrypt.org/certs/lets-encrypt-r4.pem",
287
+ "is_active": False,
288
+ "is_retired": True,
289
+ "key_technology": "RSA",
290
+ "signed_by": "isrg_root_x1",
291
+ "alternates": ["letsencrypt_intermediate_r4_cross"],
292
+ "letsencrypt_serial": "r4",
293
+ "cert.fingerprints": {
294
+ "sha1": "4D7F2DE64A8E44394FEC4A7DC8CDC498230DB829",
295
+ "sha256": "1A07529A8B3F01D231DFAD2ABDF71899200BB65CD7E03C59FA82272533355B74",
296
+ },
297
+ ".enddate": (2025, 9, 15, 16, 0, 0),
298
+ "is_self_signed": False,
299
+ },
300
+ "letsencrypt_intermediate_r4_cross": {
301
+ "display_name": "Let's Encrypt R4 (IdenTrust cross-signed)",
302
+ "url_pem": "https://letsencrypt.org/certs/lets-encrypt-r4-cross-signed.pem",
303
+ "is_active": False,
304
+ "is_retired": True,
305
+ "key_technology": "RSA",
306
+ "signed_by": "trustid_root_x3",
307
+ "alternate_of": "letsencrypt_intermediate_r4",
308
+ "letsencrypt_serial": "r4",
309
+ "cert.fingerprints": {
310
+ "sha1": "F99ABE21CDB1823C54C272E2B4904D263E8A8BFF",
311
+ "sha256": "5A8F16FDA448D783481CCA57A2428D174DAD8C60943CEB28F661AE31FD39A5FA",
312
+ },
313
+ ".enddate": (2021, 9, 29, 19, 21, 45),
314
+ "is_self_signed": False,
315
+ },
316
+ "letsencrypt_intermediate_e1": {
317
+ "display_name": "Let's Encrypt E1",
318
+ "url_pem": "https://letsencrypt.org/certs/lets-encrypt-e1.pem",
319
+ "is_active": False,
320
+ "is_retired": True,
321
+ "key_technology": "EC",
322
+ "signed_by": "isrg_root_x2",
323
+ "letsencrypt_serial": "e1",
324
+ "cert.fingerprints": {
325
+ "sha1": "091E8EA1B256A312962AF6C140C0FBF079A407B3",
326
+ "sha256": "46494E30379059DF18BE52124305E606FC59070E5B21076CE113954B60517CDA",
327
+ },
328
+ ".enddate": (2025, 9, 15, 16, 0, 0),
329
+ "is_self_signed": False,
330
+ },
331
+ "letsencrypt_intermediate_e2": {
332
+ "display_name": "Let's Encrypt E2",
333
+ "url_pem": "https://letsencrypt.org/certs/lets-encrypt-e2.pem",
334
+ "is_active": False,
335
+ "is_retired": True,
336
+ "key_technology": "EC",
337
+ "signed_by": "isrg_root_x2",
338
+ "letsencrypt_serial": "e2",
339
+ "cert.fingerprints": {
340
+ "sha1": "9A40DBEB347E861D523A707436225E16D5000133",
341
+ "sha256": "BACDE0463053CE1D62F8BE74370BBAE79D4FCAF19FC07643AEF195E6A59BD578",
342
+ },
343
+ ".enddate": (2025, 9, 15, 16, 0, 0),
344
+ "is_self_signed": False,
345
+ },
346
+ "staging_letsencrypt_root_x1": {
347
+ "display_name": "Fake LE Root X1",
348
+ "url_pem": "https://letsencrypt.org/certs/fakelerootx1.pem",
349
+ "is_trusted_root": True,
350
+ "is_untrusted_root": True,
351
+ "is_self_signed": True,
352
+ "is_active": False,
353
+ "key_technology": "RSA",
354
+ "signed_by": "staging_letsencrypt_root_x1",
355
+ "is_retired": True,
356
+ "cert.fingerprints": {
357
+ "sha1": "B3F73C419DAC14711F4B97192BF89C7DEA7A7794",
358
+ "sha256": "219C4FFCFB04F1D3AD6CA79B2B5C6C0F4493177A80FA37CCE7FC9A32DF28323D",
359
+ },
360
+ ".enddate": (2036, 3, 23, 22, 53, 46),
361
+ },
362
+ "staging_letsencrypt_intermediate_x1": {
363
+ "display_name": "Fake LE Intermediate X1",
364
+ "url_pem": "https://letsencrypt.org/certs/fakeleintermediatex1.pem",
365
+ "is_active": False,
366
+ "key_technology": "RSA",
367
+ "signed_by": "staging_letsencrypt_root_x1",
368
+ "is_retired": True,
369
+ "cert.fingerprints": {
370
+ "sha1": "4EEE7398C1A3DAF91DA16689DB8243927A271B9A",
371
+ "sha256": "A99C1B71DA32ADD9429714F71E740AFDC543C4F7F012A748D24A789B8BF3D6C7",
372
+ },
373
+ ".enddate": (2036, 5, 23, 22, 7, 59),
374
+ "is_self_signed": False,
375
+ },
376
+ "e5": {
377
+ "display_name": "Let's Encrypt E5",
378
+ "url_pem": "https://letsencrypt.org/certs/2024/e5.pem",
379
+ "is_active": False,
380
+ "key_technology": "EC",
381
+ "signed_by": "isrg_root_x2",
382
+ "alternates": ["e5_cross"],
383
+ "letsencrypt_serial": "e5",
384
+ "is_retired": True,
385
+ "cert.fingerprints": {
386
+ "sha1": "9B9C585F17E3EAE626D4583FC40DE7698A3D3B59",
387
+ "sha256": "E788D14B0436B5120BBEE3F15C15BADF08C1407FE72568A4F16F9151C380E1E3",
388
+ },
389
+ ".enddate": (2027, 3, 12, 23, 59, 59),
390
+ "is_self_signed": False,
391
+ },
392
+ "e5_cross": {
393
+ "display_name": "Let's Encrypt E5 (X1 cross-signed)",
394
+ "url_pem": "https://letsencrypt.org/certs/2024/e5-cross.pem",
395
+ "is_active": False,
396
+ "key_technology": "EC",
397
+ "signed_by": "isrg_root_x1",
398
+ "alternate_of": "e5",
399
+ "letsencrypt_serial": "e5",
400
+ "is_retired": True,
401
+ "cert.fingerprints": {
402
+ "sha1": "5F28D9C589EE4BF31A11B78C72B8D13F079DDC45",
403
+ "sha256": "5DFDB3CF31B26F23D87C09F3A0CEF642F64069A9FB7CFE29270BB5DC0F1E16BB",
404
+ },
405
+ ".enddate": (2027, 3, 12, 23, 59, 59),
406
+ "is_self_signed": False,
407
+ },
408
+ "e6": {
409
+ "display_name": "Let's Encrypt E6",
410
+ "url_pem": "https://letsencrypt.org/certs/2024/e6.pem",
411
+ "is_active": False,
412
+ "key_technology": "EC",
413
+ "signed_by": "isrg_root_x2",
414
+ "alternates": ["e6_cross"],
415
+ "letsencrypt_serial": "e6",
416
+ "is_retired": True,
417
+ "cert.fingerprints": {
418
+ "sha1": "C7BA5AA7E91080FA95E157476639736852C6BDF6",
419
+ "sha256": "065AB7D2A050F947587121765D8D070C0E1330D5798FAA42C2072749ED293762",
420
+ },
421
+ ".enddate": (2027, 3, 12, 23, 59, 59),
422
+ "is_self_signed": False,
423
+ },
424
+ "e6_cross": {
425
+ "display_name": "Let's Encrypt E6 (X1 cross-signed)",
426
+ "url_pem": "https://letsencrypt.org/certs/2024/e6-cross.pem",
427
+ "is_active": False,
428
+ "key_technology": "EC",
429
+ "signed_by": "isrg_root_x1",
430
+ "alternate_of": "e6",
431
+ "letsencrypt_serial": "e6",
432
+ "is_retired": True,
433
+ "cert.fingerprints": {
434
+ "sha1": "C94DC4831A901A9FEC0FB49B71BD49B5AAD4FAD0",
435
+ "sha256": "76E9E288AAFC0E37F4390CBF946AAD997D5C1C901B3CE513D3D8FADBABE2AB85",
436
+ },
437
+ ".enddate": (2027, 3, 12, 23, 59, 59),
438
+ "is_self_signed": False,
439
+ },
440
+ "r10": {
441
+ "display_name": "Let's Encrypt R10",
442
+ "url_pem": "https://letsencrypt.org/certs/2024/r10.pem",
443
+ "is_active": False,
444
+ "key_technology": "RSA",
445
+ "signed_by": "isrg_root_x1",
446
+ "letsencrypt_serial": "r10",
447
+ "is_retired": True,
448
+ "cert.fingerprints": {
449
+ "sha1": "00ABEFD055F9A9C784FFDEABD1DCDD8FED741436",
450
+ "sha256": "9D7C3F1AA6AD2B2EC0D5CF1E246F8D9AE6CBC9FD0755AD37BB974B1F2FB603F3",
451
+ },
452
+ ".enddate": (2027, 3, 12, 23, 59, 59),
453
+ "is_self_signed": False,
454
+ },
455
+ "r11": {
456
+ "display_name": "Let's Encrypt R11",
457
+ "url_pem": "https://letsencrypt.org/certs/2024/r11.pem",
458
+ "is_active": False,
459
+ "key_technology": "RSA",
460
+ "signed_by": "isrg_root_x1",
461
+ "letsencrypt_serial": "r11",
462
+ "is_retired": True,
463
+ "cert.fingerprints": {
464
+ "sha1": "696DB3AF0DFFC17E65C6A20D925C5A7BD24DEC7E",
465
+ "sha256": "591E9CE6C863D3A079E9FABE1478C7339A26B21269DDE795211361024AE31A44",
466
+ },
467
+ ".enddate": (2027, 3, 12, 23, 59, 59),
468
+ "is_self_signed": False,
469
+ },
470
+ "isrg_root_x2_cross": {
471
+ "display_name": "ISRG Root X2 (Cross-signed by ISRG Root X1)",
472
+ "url_pem": "https://letsencrypt.org/certs/isrg-root-x2-cross-signed.pem",
473
+ "is_trusted_root": False,
474
+ "is_active": False,
475
+ "key_technology": "EC",
476
+ "signed_by": "isrg_root_x1",
477
+ "alternate_of": "isrg_root_x2",
478
+ "is_retired": True,
479
+ "cert.fingerprints": {
480
+ "sha1": "151682F5218C0A511C28F4060A73B9CA78CE9A53",
481
+ "sha256": "8B05B68CC659E5ED0FCB38F2C942FBFD200E6F2FF9F85D63C6994EF5E0B02701",
482
+ },
483
+ ".enddate": (2025, 9, 15, 16, 0, 0),
484
+ "is_self_signed": False,
485
+ },
486
+ "letsencrypt_staging_root_x2_signed_by_x2": {
487
+ "display_name": "(STAGING) Bogus Broccoli X2 (X1 cross-signed)",
488
+ "url_pem": "https://letsencrypt.org/certs/staging/letsencrypt-stg-root-x2-signed-by-x1.pem",
489
+ "is_trusted_root": True,
490
+ "is_untrusted_root": True,
491
+ "is_self_signed": False,
492
+ "signed_by": "letsencrypt_staging_root_x1",
493
+ "alternate_of": "letsencrypt_staging_root_x2",
494
+ "is_active": False,
495
+ "key_technology": "EC",
496
+ "cert.fingerprints": {
497
+ "sha1": "70CB7923F66CB2678B050CEF38D5B4CB28489E88",
498
+ "sha256": "32D21AF6FC87417A55D7E23C6992B8CE0CB9B5FCD85DA30D194156D53758E4C5",
499
+ },
500
+ ".enddate": (2025, 9, 15, 16, 0, 0),
501
+ "compatibility": {"All": ("<0", ">0", "Untrusted Fake Root")},
502
+ "is_retired": True,
503
+ },
504
+ "e7": {
505
+ "display_name": "Let's Encrypt E7",
506
+ "url_pem": "https://letsencrypt.org/certs/2024/e7.pem",
507
+ "is_active": False,
508
+ "key_technology": "EC",
509
+ "signed_by": "isrg_root_x2",
510
+ "alternates": ["e7_cross"],
511
+ "letsencrypt_serial": "e7",
512
+ "is_retired": True,
513
+ "cert.fingerprints": {
514
+ "sha1": "D6C9554B96C89F87A9EEAB5C32CC37D3AF965737",
515
+ "sha256": "54715420224C5B65BEED018DC3940D7338C577E322D5488F633D8C6A8FED61B2",
516
+ },
517
+ ".enddate": (2027, 3, 12, 23, 59, 59),
518
+ "is_self_signed": False,
519
+ },
520
+ "e7_cross": {
521
+ "display_name": "Let's Encrypt E7 (X1 cross-signed)",
522
+ "url_pem": "https://letsencrypt.org/certs/2024/e7-cross.pem",
523
+ "is_active": False,
524
+ "key_technology": "EC",
525
+ "signed_by": "isrg_root_x1",
526
+ "alternate_of": "e7",
527
+ "letsencrypt_serial": "e7",
528
+ "is_retired": True,
529
+ "cert.fingerprints": {
530
+ "sha1": "3B73C17E3DF87CF3AA77F1389219EB5EDD519E7F",
531
+ "sha256": "AEB1FD7410E83BC96F5DA3C6A7C2C1BB836D1FA5CB86E708515890E428A8770B",
532
+ },
533
+ ".enddate": (2027, 3, 12, 23, 59, 59),
534
+ "is_self_signed": False,
535
+ },
536
+ "e8": {
537
+ "display_name": "Let's Encrypt E8",
538
+ "url_pem": "https://letsencrypt.org/certs/2024/e8.pem",
539
+ "is_active": False,
540
+ "key_technology": "EC",
541
+ "signed_by": "isrg_root_x2",
542
+ "alternates": ["e8_cross"],
543
+ "letsencrypt_serial": "e8",
544
+ "is_retired": True,
545
+ "cert.fingerprints": {
546
+ "sha1": "E1CC565BEECAE8862A7D37BD291BEB214E1B1C88",
547
+ "sha256": "AC1274542267F17B525535B5563BF731FEBB182533B46A82DC869CB64EB528C0",
548
+ },
549
+ ".enddate": (2027, 3, 12, 23, 59, 59),
550
+ "is_self_signed": False,
551
+ },
552
+ "e8_cross": {
553
+ "display_name": "Let's Encrypt E8 (X1 cross-signed)",
554
+ "url_pem": "https://letsencrypt.org/certs/2024/e8-cross.pem",
555
+ "is_active": False,
556
+ "key_technology": "EC",
557
+ "signed_by": "isrg_root_x1",
558
+ "alternate_of": "e8",
559
+ "letsencrypt_serial": "e8",
560
+ "is_retired": True,
561
+ "cert.fingerprints": {
562
+ "sha1": "54317EB0765F0BC674855184EB8374B4199E4655",
563
+ "sha256": "83624FD338C8D9B023C18A67CB7A9C0519DA43D11775B4C6CBDAD45C3D997C52",
564
+ },
565
+ ".enddate": (2027, 3, 12, 23, 59, 59),
566
+ "is_self_signed": False,
567
+ },
568
+ "e9": {
569
+ "display_name": "Let's Encrypt E9",
570
+ "url_pem": "https://letsencrypt.org/certs/2024/e9.pem",
571
+ "is_active": False,
572
+ "key_technology": "EC",
573
+ "signed_by": "isrg_root_x2",
574
+ "alternates": ["e9_cross"],
575
+ "letsencrypt_serial": "e9",
576
+ "is_retired": True,
577
+ "cert.fingerprints": {
578
+ "sha1": "C852082BA3D0B89674F8258803FD5A3CF02DEA4D",
579
+ "sha256": "4185DF97806C2BA76F1D79823F112FFA639A49CCDC990908102067AB6412B886",
580
+ },
581
+ ".enddate": (2027, 3, 12, 23, 59, 59),
582
+ "is_self_signed": False,
583
+ },
584
+ "e9_cross": {
585
+ "display_name": "Let's Encrypt E9 (X1 cross-signed)",
586
+ "url_pem": "https://letsencrypt.org/certs/2024/e9-cross.pem",
587
+ "is_active": False,
588
+ "key_technology": "EC",
589
+ "signed_by": "isrg_root_x1",
590
+ "alternate_of": "e9",
591
+ "letsencrypt_serial": "e9",
592
+ "is_retired": True,
593
+ "cert.fingerprints": {
594
+ "sha1": "62E5E611F170792D7D6CDD45A6B8A06783EC31EE",
595
+ "sha256": "FDE88F2D4F8913D3DC1664D5F8DE51E07FE2ABFED93B45ACAD5A29BFEBAA23FB",
596
+ },
597
+ ".enddate": (2027, 3, 12, 23, 59, 59),
598
+ "is_self_signed": False,
599
+ },
600
+ "r12": {
601
+ "display_name": "Let's Encrypt R12",
602
+ "url_pem": "https://letsencrypt.org/certs/2024/r12.pem",
603
+ "is_active": False,
604
+ "key_technology": "RSA",
605
+ "signed_by": "isrg_root_x1",
606
+ "letsencrypt_serial": "r12",
607
+ "is_retired": True,
608
+ "cert.fingerprints": {
609
+ "sha1": "EE44782835D8FB31394DA5CEB840DC93849BCF5A",
610
+ "sha256": "131FCE7784016899A5A00203A9EFC80F18EBBD75580717EDC1553580930836EC",
611
+ },
612
+ ".enddate": (2027, 3, 12, 23, 59, 59),
613
+ "is_self_signed": False,
614
+ },
615
+ "r13": {
616
+ "display_name": "Let's Encrypt R13",
617
+ "url_pem": "https://letsencrypt.org/certs/2024/r13.pem",
618
+ "is_active": False,
619
+ "key_technology": "RSA",
620
+ "signed_by": "isrg_root_x1",
621
+ "letsencrypt_serial": "r13",
622
+ "is_retired": True,
623
+ "cert.fingerprints": {
624
+ "sha1": "22FF89586561FC2D52F77491E9F1EFF1B80BE33E",
625
+ "sha256": "D3B128216A843F8EF1321501F5DF52A5DF52939EE2C19297712CD3DE4D419354",
626
+ },
627
+ ".enddate": (2027, 3, 12, 23, 59, 59),
628
+ "is_self_signed": False,
629
+ },
630
+ "r14": {
631
+ "display_name": "Let's Encrypt R14",
632
+ "url_pem": "https://letsencrypt.org/certs/2024/r14.pem",
633
+ "is_active": False,
634
+ "key_technology": "RSA",
635
+ "signed_by": "isrg_root_x1",
636
+ "letsencrypt_serial": "r14",
637
+ "is_retired": True,
638
+ "cert.fingerprints": {
639
+ "sha1": "47E0467E82B52DDE4CB867CFBEE75201EE04A9D1",
640
+ "sha256": "24D45AA9B8D6053D281F3842C8CC0C6C1AF7CCDFD42DD5C12F6A74FA9323F7A2",
641
+ },
642
+ ".enddate": (2027, 3, 12, 23, 59, 59),
643
+ "is_self_signed": False,
644
+ },
645
+ }
646
+
647
+ CERT_CAS_DATA: Dict[str, CERT_CA_PAYLOAD] = {
648
+ "isrg_root_x1": {
649
+ "display_name": "ISRG Root X1",
650
+ "url_pem": "https://letsencrypt.org/certs/isrgrootx1.pem",
651
+ "is_trusted_root": True,
652
+ "is_self_signed": True,
653
+ "signed_by": "isrg_root_x1",
654
+ "is_active": True,
655
+ "key_technology": "RSA",
656
+ "alternates": ["isrg_root_x1_cross"],
657
+ "cert.fingerprints": {
658
+ "sha1": "CABD2A79A1076A31F21D253635CB039D4329A5E8",
659
+ "sha256": "96BCEC06264976F37460779ACF28C5A7CFE8A3C0AAE11A8FFCEE05C0BDDF08C6",
660
+ },
661
+ ".enddate": (2035, 6, 4, 11, 4, 38),
662
+ "compatibility": {
663
+ "Windows": (
664
+ ">= XP SP3",
665
+ None,
666
+ "unless Automatic Root Certificate Updates have been disabled",
667
+ ),
668
+ "Windows Server": (
669
+ ">= 2008",
670
+ None,
671
+ "unless Automatic Root Certificate Updates have been disabled",
672
+ ),
673
+ "macOS": (">= 10.12.1 Sierra", None, None),
674
+ "iOS": (">= 10", None, None),
675
+ "Android": (">= 7.1.1", None, None),
676
+ "Firefox": (">= 50.0", None, None),
677
+ "Ubuntu": (">= 12.04 Precise Pangolin ", None, "with updates applied"),
678
+ "Debian": (">= 8 / Jessie", None, "with updates applied"),
679
+ "RHEL 6": (">= 6.10", None, "with updates applied"),
680
+ "RHEL 7": (">= 7.4", None, "with updates applied"),
681
+ "RHEL 8": (">= 8", None, None),
682
+ "Java 7": (">= 7u151", None, None),
683
+ "Java 8": (">= 8u141", None, None),
684
+ "Java 9": (">= 9", None, None),
685
+ "NSS": (">= 3.26", None, None),
686
+ "Chrome": (
687
+ ">= 105",
688
+ None,
689
+ "earlier versions use the operating system trust store",
690
+ ),
691
+ "PlayStation PS4": (">= PS4 v8.0.0", None, None),
692
+ },
693
+ },
694
+ "isrg_root_x2": {
695
+ "display_name": "ISRG Root X2",
696
+ "url_pem": "https://letsencrypt.org/certs/isrg-root-x2.pem",
697
+ "is_trusted_root": True,
698
+ "is_self_signed": True,
699
+ "signed_by": "isrg_root_x2",
700
+ "is_active": True,
701
+ "key_technology": "EC",
702
+ "alternates": ["isrg_root_x2_cross_2025", "isrg_root_x2_cross"],
703
+ "cert.fingerprints": {
704
+ "sha1": "BDB1B93CD5978D45C6261455F8DB95C75AD153AF",
705
+ "sha256": "69729B8E15A86EFC177A57AFB7171DFC64ADD28C2FCA8CF1507E34453CCB1470",
706
+ },
707
+ ".enddate": (2040, 9, 17, 16, 0, 0),
708
+ "compatibility": {
709
+ "Windows": (
710
+ ">= XP SP3",
711
+ None,
712
+ "unless Automatic Root Certificate Updates have been disabled",
713
+ ),
714
+ "Windows Server": (
715
+ ">= 2008",
716
+ None,
717
+ "unless Automatic Root Certificate Updates have been disabled",
718
+ ),
719
+ "macOS": (">= 13", None, None),
720
+ "iOS": (">= 16", None, None),
721
+ "Android": (">= 14", None, None),
722
+ "Firefox": (">= 97", None, None),
723
+ "Ubuntu": (">= 18.04 Bionic Beaver ", None, None),
724
+ "Debian": (">= 12/ Bookworm", None, None),
725
+ "RHEL 7": (">= 7.9", None, "with updates applied"),
726
+ "RHEL 8": (">= 8.6", None, "with updates applied"),
727
+ "RHEL 9": (">= 9.1", None, "with updates applied"),
728
+ "Java 8": (">= 8u141", None, None),
729
+ "Java 11": (">= 11.0.22", None, None),
730
+ "Java 17": (">= 17.0.10", None, None),
731
+ "Java 21": (">= 21.0.2", None, None),
732
+ "Java 22": (">= 22", None, None),
733
+ "NSS": (">= 3.74", None, None),
734
+ "Chrome": (
735
+ ">= 105",
736
+ None,
737
+ "earlier versions use the operating system trust store",
738
+ ),
739
+ },
740
+ },
741
+ "isrg_root_x2_cross_2025": {
742
+ "display_name": "Let's Encrypt ISRG Root X2 (cross-signed by ISRG Root X1)",
743
+ "url_pem": "https://letsencrypt.org/certs/gen-y/root-x2-by-x1.pem",
744
+ "signed_by": "isrg_root_x1",
745
+ "is_active": True,
746
+ "key_technology": "EC",
747
+ "cert.fingerprints": {
748
+ "sha1": "3C34E356C7FC17F5ACF04824BC587C6C623951A2",
749
+ "sha256": "EE5F7ABD6981BB0255632CD8F49283451B4B18844D12040B44EE00F07B8FE2C6",
750
+ },
751
+ ".enddate": (2032, 9, 2, 23, 59, 59),
752
+ "is_self_signed": False,
753
+ "is_retired": False,
754
+ "is_trusted_root": False,
755
+ "alternate_of": "isrg_root_x2",
756
+ },
757
+ "isrg_root_ye": {
758
+ "display_name": "ISRG Root YE",
759
+ "url_pem": "https://letsencrypt.org/certs/gen-y/root-ye.pem",
760
+ "signed_by": "isrg_root_ye",
761
+ "is_active": True,
762
+ "key_technology": "EC",
763
+ "cert.fingerprints": {
764
+ "sha1": "A9571557A77DB78FFAC2E97B57B898569039C340",
765
+ "sha256": "E14FFCAD5B0025731006CAA43A121A22D8E9700F4FB9CF852F02A708AA5D5666",
766
+ },
767
+ ".enddate": (2045, 9, 2, 23, 59, 59),
768
+ "is_self_signed": True,
769
+ "is_retired": False,
770
+ "is_trusted_root": False,
771
+ "is_untrusted_root": True,
772
+ "alternates": ["isrg_root_ye_cross"],
773
+ },
774
+ "isrg_root_ye_cross": {
775
+ "display_name": "ISRG Root YE (cross-signed by ISRG Root X2)",
776
+ "url_pem": "https://letsencrypt.org/certs/gen-y/root-ye-by-x2.pem",
777
+ "signed_by": "isrg_root_x2",
778
+ "is_active": True,
779
+ "key_technology": "EC",
780
+ "cert.fingerprints": {
781
+ "sha1": "F37620FC4B1CDDD2A3D74B1D5E8DB42E244CA006",
782
+ "sha256": "0FC0901CCA2BAE9E9FDBB02D50D02F1094F7B36672086991B9E897626DC485F0",
783
+ },
784
+ ".enddate": (2032, 9, 2, 23, 59, 59),
785
+ "is_self_signed": False,
786
+ "is_retired": False,
787
+ "is_trusted_root": False,
788
+ "alternate_of": "isrg_root_ye",
789
+ },
790
+ "isrg_root_yr": {
791
+ "display_name": "ISRG Root YR",
792
+ "url_pem": "https://letsencrypt.org/certs/gen-y/root-yr.pem",
793
+ "signed_by": "isrg_root_yr",
794
+ "is_active": True,
795
+ "key_technology": "RSA",
796
+ "cert.fingerprints": {
797
+ "sha1": "C5F111DA84F7DEF8E6F3F99F8F5F36FF85BAB1B1",
798
+ "sha256": "E57B7E6F150C419102E8D5C055729FF967B9D1A829BF00CEC89CA604EBF4A86F",
799
+ },
800
+ ".enddate": (2045, 9, 2, 23, 59, 59),
801
+ "is_self_signed": True,
802
+ "is_retired": False,
803
+ "is_trusted_root": False,
804
+ "is_untrusted_root": True,
805
+ "alternates": ["isrg_root_yr_cross"],
806
+ },
807
+ "isrg_root_yr_cross": {
808
+ "display_name": "ISRG Root YR (cross-signed by ISRG Root X1)",
809
+ "url_pem": "https://letsencrypt.org/certs/gen-y/root-yr-by-x1.pem",
810
+ "signed_by": "isrg_root_x1",
811
+ "is_active": True,
812
+ "key_technology": "RSA",
813
+ "cert.fingerprints": {
814
+ "sha1": "AB9D0263244DD0326EB67015705A667E79CFE998",
815
+ "sha256": "072639D0B140D5BFFAE16AD9C3F6CC6086040621F51EE61A6D46A8915C07CF76",
816
+ },
817
+ ".enddate": (2032, 9, 2, 23, 59, 59),
818
+ "is_self_signed": False,
819
+ "is_retired": False,
820
+ "is_trusted_root": False,
821
+ "alternate_of": "isrg_root_yr",
822
+ },
823
+ "ye1": {
824
+ "display_name": "Let's Encrypt YE1",
825
+ "url_pem": "https://letsencrypt.org/certs/gen-y/int-ye1.pem",
826
+ "signed_by": "isrg_root_ye",
827
+ "is_active": True,
828
+ "key_technology": "EC",
829
+ "cert.fingerprints": {
830
+ "sha1": "D09370A9864982A5047DA46373540256D08A3C81",
831
+ "sha256": "A2372D06431E9716365EEED47EC020351497D182FCC038E457E58168A03CAC07",
832
+ },
833
+ ".enddate": (2028, 9, 2, 23, 59, 59),
834
+ "is_self_signed": False,
835
+ "is_retired": False,
836
+ "is_trusted_root": False,
837
+ "letsencrypt_serial": "ye1",
838
+ },
839
+ "ye2": {
840
+ "display_name": "Let's Encrypt YE2",
841
+ "url_pem": "https://letsencrypt.org/certs/gen-y/int-ye2.pem",
842
+ "signed_by": "isrg_root_ye",
843
+ "is_active": True,
844
+ "key_technology": "EC",
845
+ "cert.fingerprints": {
846
+ "sha1": "F8158CA8A3A7C5DBD7842218F5D949CEC83ACDBA",
847
+ "sha256": "97658DE8C68DFA98ACE1E5028A63D54A1AAE911B3E21471076C6850CD08CBAB4",
848
+ },
849
+ ".enddate": (2028, 9, 2, 23, 59, 59),
850
+ "is_self_signed": False,
851
+ "is_retired": False,
852
+ "is_trusted_root": False,
853
+ "letsencrypt_serial": "ye2",
854
+ },
855
+ "yr1": {
856
+ "display_name": "Let's Encrypt YR1",
857
+ "url_pem": "https://letsencrypt.org/certs/gen-y/int-yr1.pem",
858
+ "signed_by": "isrg_root_yr",
859
+ "is_active": True,
860
+ "key_technology": "RSA",
861
+ "cert.fingerprints": {
862
+ "sha1": "CBCFD09CE3CD22D99D94E58F92E9898FBEE51A5E",
863
+ "sha256": "13949634D99CD6FD6AA80BC034FEFACCEB1969FEEF986586713ECDBB05758D3F",
864
+ },
865
+ ".enddate": (2028, 9, 2, 23, 59, 59),
866
+ "is_self_signed": False,
867
+ "is_retired": False,
868
+ "is_trusted_root": False,
869
+ "letsencrypt_serial": "yr1",
870
+ },
871
+ "yr2": {
872
+ "display_name": "Let's Encrypt YR2",
873
+ "url_pem": "https://letsencrypt.org/certs/gen-y/int-yr2.pem",
874
+ "signed_by": "isrg_root_yr",
875
+ "is_active": True,
876
+ "key_technology": "RSA",
877
+ "cert.fingerprints": {
878
+ "sha1": "2D74D6DFD96EEA55AD7BAAFA0D3C6552B2DADC37",
879
+ "sha256": "238B85A0099C65B970477D5724F1A1D475CE5058CFFE4EFA8733899BDB863C47",
880
+ },
881
+ ".enddate": (2028, 9, 2, 23, 59, 59),
882
+ "is_self_signed": False,
883
+ "is_retired": False,
884
+ "is_trusted_root": False,
885
+ "letsencrypt_serial": "yr2",
886
+ },
887
+ "ye3": {
888
+ "display_name": "Let's Encrypt YE3",
889
+ "url_pem": "https://letsencrypt.org/certs/gen-y/int-ye3.pem",
890
+ "signed_by": "isrg_root_ye",
891
+ "is_active": False,
892
+ "is_backup": True,
893
+ "key_technology": "EC",
894
+ "cert.fingerprints": {
895
+ "sha1": "A23DA087F94A15259F251FDC6620616864BF54EF",
896
+ "sha256": "82BCFC482CC19F71E6F98F4A027616EBDA6D47096D408B336160D1C0EF8B995A",
897
+ },
898
+ ".enddate": (2028, 9, 2, 23, 59, 59),
899
+ "is_self_signed": False,
900
+ "is_retired": False,
901
+ "is_trusted_root": False,
902
+ "letsencrypt_serial": "ye3",
903
+ },
904
+ "yr3": {
905
+ "display_name": "Let's Encrypt YR3",
906
+ "url_pem": "https://letsencrypt.org/certs/gen-y/int-yr3.pem",
907
+ "signed_by": "isrg_root_yr",
908
+ "is_active": False,
909
+ "is_backup": True,
910
+ "key_technology": "RSA",
911
+ "cert.fingerprints": {
912
+ "sha1": "5F89F238597B90392073AC3D36FD9AC4FA911420",
913
+ "sha256": "35500CB63B8D9769528D65D87220F51C069807A595ACBF2FB6ECA38FBE0A4BD2",
914
+ },
915
+ ".enddate": (2028, 9, 2, 23, 59, 59),
916
+ "is_self_signed": False,
917
+ "is_retired": False,
918
+ "is_trusted_root": False,
919
+ "letsencrypt_serial": "yr3",
920
+ },
921
+ "letsencrypt_staging_root_x1": {
922
+ "display_name": "(STAGING) Pretend Pear X1",
923
+ "url_pem": "https://letsencrypt.org/certs/staging/letsencrypt-stg-root-x1.pem",
924
+ "is_trusted_root": True,
925
+ "is_untrusted_root": True,
926
+ "is_self_signed": True,
927
+ "signed_by": "letsencrypt_staging_root_x1",
928
+ "is_active": True,
929
+ "key_technology": "RSA",
930
+ "cert.fingerprints": {
931
+ "sha1": "66493BA4F36D1731729B1118C7F5E2D540E3F37B",
932
+ "sha256": "E70570A989F8565AABDF7CAE27ABD1621872D6A3F811E3FEF27E3DBA02912198",
933
+ },
934
+ ".enddate": (2035, 6, 4, 11, 4, 38),
935
+ "compatibility": {"All": ("<0", ">0", "Untrusted Fake Root")},
936
+ },
937
+ "letsencrypt_staging_root_x2": {
938
+ "display_name": "(STAGING) Bogus Broccoli X2",
939
+ "url_pem": "https://letsencrypt.org/certs/staging/letsencrypt-stg-root-x2.pem",
940
+ "is_trusted_root": True,
941
+ "is_untrusted_root": True,
942
+ "is_self_signed": True,
943
+ "signed_by": "letsencrypt_staging_root_x2",
944
+ "is_active": True,
945
+ "key_technology": "EC",
946
+ "cert.fingerprints": {
947
+ "sha1": "A465AF9AF04F1A86A2701B987B3ED3A75D50ECEA",
948
+ "sha256": "9B2A339FE6A3E85585C4CD75536CB8C1CF7CD603B9A64BEC2521858AE48DA85D",
949
+ },
950
+ ".enddate": (2040, 9, 17, 16, 0, 0),
951
+ "compatibility": {"All": ("<0", ">0", "Untrusted Fake Root")},
952
+ "alternates": ["letsencrypt_staging_root_x2_signed_by_x2"],
953
+ },
954
+ }
955
+
956
+ _CERT_CAS_DEPRECATED_ORDER = [
957
+ "trustid_root_x3",
958
+ "isrg_root_x1_cross",
959
+ "letsencrypt_ocsp_root_x1",
960
+ "letsencrypt_intermediate_x1",
961
+ "letsencrypt_intermediate_x1_cross",
962
+ "letsencrypt_intermediate_x2",
963
+ "letsencrypt_intermediate_x2_cross",
964
+ "letsencrypt_intermediate_x3",
965
+ "letsencrypt_intermediate_x3_cross",
966
+ "letsencrypt_intermediate_x4",
967
+ "letsencrypt_intermediate_x4_cross",
968
+ "letsencrypt_intermediate_r3",
969
+ "letsencrypt_intermediate_r3_cross",
970
+ "letsencrypt_intermediate_r4",
971
+ "letsencrypt_intermediate_r4_cross",
972
+ "letsencrypt_intermediate_e1",
973
+ "letsencrypt_intermediate_e2",
974
+ "e5",
975
+ "e5_cross",
976
+ "e6",
977
+ "e6_cross",
978
+ "r10",
979
+ "r11",
980
+ "staging_letsencrypt_root_x1",
981
+ "staging_letsencrypt_intermediate_x1",
982
+ "isrg_root_x2_cross",
983
+ "e7",
984
+ "e7_cross",
985
+ "e8",
986
+ "e8_cross",
987
+ "e9",
988
+ "e9_cross",
989
+ "r12",
990
+ "r13",
991
+ "r14",
992
+ "letsencrypt_staging_root_x2_signed_by_x2",
993
+ ]
994
+ _CERT_CAS_ORDER = [
995
+ "isrg_root_x1",
996
+ "isrg_root_x2",
997
+ "isrg_root_x2_cross_2025",
998
+ "isrg_root_ye",
999
+ "isrg_root_ye_cross",
1000
+ "isrg_root_yr",
1001
+ "isrg_root_yr_cross",
1002
+ "ye1",
1003
+ "ye2",
1004
+ "yr1",
1005
+ "yr2",
1006
+ "ye3",
1007
+ "yr3",
1008
+ "letsencrypt_staging_root_x1",
1009
+ "letsencrypt_staging_root_x2",
1010
+ ]
1011
+
1012
+ # Prefer established roots; pending roots are available only as explicit options.
1013
+ DEFAULT_CA_PREFERENCES = [
1014
+ "isrg_root_x2",
1015
+ "isrg_root_x1",
1016
+ "isrg_root_ye",
1017
+ "isrg_root_yr",
1018
+ ]
1019
+
1020
+
1021
+ # these should be a listing of serials
1022
+ # e.g.: ("x1", "x2", "x3", "x4", "r3", "r4", "e1", "e2")
1023
+ CA_LE_INTERMEDIATES = []
1024
+ CA_LE_INTERMEDIATES_CROSSED = []
1025
+ for _cert_id, _payload in CERT_CAS_DATA.items():
1026
+ _serial = _payload.get("letsencrypt_serial")
1027
+ if not _serial:
1028
+ continue
1029
+ if not _payload.get("alternate_of"):
1030
+ if not _payload.get("is_trusted_root"):
1031
+ CA_LE_INTERMEDIATES.append(_serial)
1032
+ else:
1033
+ CA_LE_INTERMEDIATES_CROSSED.append(_serial)
1034
+
1035
+
1036
+ # LOAD THE CERTS INTO THE SYSTEM
1037
+ _dir_here = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
1038
+ _dir_certs = os.path.join(_dir_here, "letsencrypt-certs")
1039
+ for cert_id, cert_data in CERT_CAS_DATA.items():
1040
+ _filename = cert_data["url_pem"].split("/")[-1] # type: ignore[attr-defined]
1041
+ _filepath = os.path.join(_dir_certs, _filename)
1042
+ with open(_filepath, "r") as _fp:
1043
+ cert_pem_text = _fp.read()
1044
+ cert_pem_text = cleanup_pem_text(cert_pem_text)
1045
+ cert_data["cert_pem"] = cert_pem_text
1046
+
1047
+
1048
+ def download_letsencrypt_certificates(
1049
+ *, timeout: Optional[Timeout] = None
1050
+ ) -> Dict[str, Any]:
1051
+ """
1052
+ DEPRECATED
1053
+
1054
+ nothing calls this. may be useful for testing to ensure the certs have not
1055
+ changed on disk, such as the whitespace issue in 2021/02
1056
+
1057
+ download the known LetsEncrypt certificates
1058
+
1059
+ * correct usage of `requests`
1060
+ - currently using `.content`, which is raw bytes
1061
+ - usually one uses `.text`, which is `.content` that is decoded
1062
+ - there was some concern that triggered this utf8 decode at some point...
1063
+ """
1064
+ # ???: raise Exception if the cert_pem changes?
1065
+ certs = copy.deepcopy(CERT_CAS_DATA)
1066
+ for c in list(certs.keys()):
1067
+ resp = requests.get(certs[c]["url_pem"], timeout=get_timeout(timeout))
1068
+ if resp.status_code != 200:
1069
+ raise ValueError("Could not load certificate")
1070
+ cert_pem_text = resp.text
1071
+ cert_pem_text = cleanup_pem_text(cert_pem_text)
1072
+ certs[c]["cert_pem"] = cert_pem_text
1073
+ certs[c]["cert_pem_md5"] = md5_text(cert_pem_text)
1074
+ return certs