@@ -108,6 +108,34 @@ def _send_json(self, data: dict | list) -> None:
108108 self .wfile .write (payload )
109109
110110
111+ def _export_expired_client_cert (
112+ ca : trustme .CA , client_cert : trustme .LeafCert , path : Path
113+ ) -> None :
114+ """Re-sign a client certificate with expired validity dates.
115+
116+ Parameters:
117+ ca: The CA that issued the original client certificate.
118+ client_cert: The original client leaf certificate.
119+ path: File path to write the expired client certificate PEM.
120+ """
121+ original = client_cert .cert_chain_pems [0 ].bytes ()
122+ from cryptography .x509 import load_pem_x509_certificate
123+
124+ orig_cert = load_pem_x509_certificate (original )
125+ now = datetime .datetime .now (datetime .UTC )
126+ builder = CertificateBuilder ()
127+ builder = builder .subject_name (orig_cert .subject )
128+ builder = builder .issuer_name (orig_cert .issuer )
129+ builder = builder .public_key (orig_cert .public_key ())
130+ builder = builder .serial_number (random_serial_number ())
131+ builder = builder .not_valid_before (now - datetime .timedelta (days = 365 ))
132+ builder = builder .not_valid_after (now - datetime .timedelta (seconds = 1 ))
133+ for ext in orig_cert .extensions :
134+ builder = builder .add_extension (ext .value , ext .critical )
135+ expired_cert = builder .sign (ca ._private_key , hashes .SHA256 ())
136+ path .write_bytes (expired_cert .public_bytes (serialization .Encoding .PEM ))
137+
138+
111139def _export_expired_ca_cert (ca : trustme .CA , path : Path ) -> None :
112140 """Re-sign a trustme CA certificate with expired validity dates.
113141
@@ -118,18 +146,18 @@ def _export_expired_ca_cert(ca: trustme.CA, path: Path) -> None:
118146 ca: The trustme CA whose certificate and key to use.
119147 path: File path to write the expired CA certificate PEM.
120148 """
121- original = ca ._certificate # noqa: SLF001
122- now = datetime .datetime .now (datetime .timezone . utc )
149+ original = ca ._certificate
150+ now = datetime .datetime .now (datetime .UTC )
123151 builder = CertificateBuilder ()
124152 builder = builder .subject_name (original .subject )
125153 builder = builder .issuer_name (original .issuer )
126154 builder = builder .public_key (original .public_key ())
127155 builder = builder .serial_number (random_serial_number ())
128156 builder = builder .not_valid_before (now - datetime .timedelta (days = 365 ))
129- builder = builder .not_valid_after (now - datetime .timedelta (days = 1 ))
157+ builder = builder .not_valid_after (now - datetime .timedelta (seconds = 1 ))
130158 for ext in original .extensions :
131159 builder = builder .add_extension (ext .value , ext .critical )
132- expired_cert = builder .sign (ca ._private_key , hashes .SHA256 ()) # noqa: SLF001
160+ expired_cert = builder .sign (ca ._private_key , hashes .SHA256 ())
133161 path .write_bytes (expired_cert .public_bytes (serialization .Encoding .PEM ))
134162
135163
@@ -211,6 +239,20 @@ def main() -> None:
211239 _export_expired_ca_cert (ca , certs_dir / "expired-ca.crt" )
212240 print (f" Expired CA cert: { certs_dir / 'expired-ca.crt' } " )
213241
242+ # Export untrusted client certificate (issued by a different CA)
243+ untrusted_client = untrusted_ca .issue_cert ("tls-e2e-untrusted-client" )
244+ untrusted_client .private_key_pem .write_to_path (
245+ str (certs_dir / "untrusted-client.key" )
246+ )
247+ with (certs_dir / "untrusted-client.crt" ).open ("wb" ) as f :
248+ for blob in untrusted_client .cert_chain_pems :
249+ f .write (blob .bytes ())
250+ print (f" Untrusted client cert: { certs_dir / 'untrusted-client.crt' } " )
251+
252+ # Export expired client certificate (signed by main CA but with past dates)
253+ _export_expired_client_cert (ca , client_cert , certs_dir / "expired-client.crt" )
254+ print (f" Expired client cert: { certs_dir / 'expired-client.crt' } " )
255+
214256 print ("=" * 60 )
215257 print ("Starting servers..." )
216258 print ("=" * 60 )
0 commit comments