|
11 | 11 | Certificates are generated on-the-fly using trustme at server startup. |
12 | 12 | """ |
13 | 13 |
|
| 14 | +import datetime |
14 | 15 | import json |
15 | 16 | import ssl |
16 | 17 | import sys |
|
21 | 22 | from typing import Any |
22 | 23 |
|
23 | 24 | import trustme |
| 25 | +from cryptography.hazmat.primitives import hashes, serialization |
| 26 | +from cryptography.x509 import CertificateBuilder, random_serial_number |
24 | 27 |
|
25 | 28 | MODEL_ID = "mock-tls-model" |
26 | 29 |
|
@@ -105,6 +108,31 @@ def _send_json(self, data: dict | list) -> None: |
105 | 108 | self.wfile.write(payload) |
106 | 109 |
|
107 | 110 |
|
| 111 | +def _export_expired_ca_cert(ca: trustme.CA, path: Path) -> None: |
| 112 | + """Re-sign a trustme CA certificate with expired validity dates. |
| 113 | +
|
| 114 | + Creates a copy of the CA's self-signed certificate but with validity |
| 115 | + dates set in the past, making it an expired certificate. |
| 116 | +
|
| 117 | + Parameters: |
| 118 | + ca: The trustme CA whose certificate and key to use. |
| 119 | + path: File path to write the expired CA certificate PEM. |
| 120 | + """ |
| 121 | + original = ca._certificate # noqa: SLF001 |
| 122 | + now = datetime.datetime.now(datetime.timezone.utc) |
| 123 | + builder = CertificateBuilder() |
| 124 | + builder = builder.subject_name(original.subject) |
| 125 | + builder = builder.issuer_name(original.issuer) |
| 126 | + builder = builder.public_key(original.public_key()) |
| 127 | + builder = builder.serial_number(random_serial_number()) |
| 128 | + builder = builder.not_valid_before(now - datetime.timedelta(days=365)) |
| 129 | + builder = builder.not_valid_after(now - datetime.timedelta(days=1)) |
| 130 | + for ext in original.extensions: |
| 131 | + builder = builder.add_extension(ext.value, ext.critical) |
| 132 | + expired_cert = builder.sign(ca._private_key, hashes.SHA256()) # noqa: SLF001 |
| 133 | + path.write_bytes(expired_cert.public_bytes(serialization.Encoding.PEM)) |
| 134 | + |
| 135 | + |
108 | 136 | def _make_tls_context( |
109 | 137 | ca: trustme.CA, |
110 | 138 | server_cert: trustme.LeafCert, |
@@ -174,6 +202,15 @@ def main() -> None: |
174 | 202 | print(f" Client cert: {certs_dir / 'client.crt'}") |
175 | 203 | print(f" Client key: {certs_dir / 'client.key'}") |
176 | 204 |
|
| 205 | + # Export untrusted CA certificate (from a separate CA that did not sign the server cert) |
| 206 | + untrusted_ca = trustme.CA() |
| 207 | + untrusted_ca.cert_pem.write_to_path(str(certs_dir / "untrusted-ca.crt")) |
| 208 | + print(f" Untrusted CA cert: {certs_dir / 'untrusted-ca.crt'}") |
| 209 | + |
| 210 | + # Export expired CA certificate (re-signed with past validity dates) |
| 211 | + _export_expired_ca_cert(ca, certs_dir / "expired-ca.crt") |
| 212 | + print(f" Expired CA cert: {certs_dir / 'expired-ca.crt'}") |
| 213 | + |
177 | 214 | print("=" * 60) |
178 | 215 | print("Starting servers...") |
179 | 216 | print("=" * 60) |
|
0 commit comments