qh3_mutual_tls_patch
Runtime monkey-patch that adds mutual TLS (client certificate authentication) support to qh3's server-side TLS 1.3 implementation.
Problem
qh3's TLS 1.3 server does not send a CertificateRequest message during the handshake, so the client never presents its certificate. This makes it impossible to use mutual TLS authentication in QUIC servers built with qh3.
Solution
This package patches qh3's Context class at runtime to:
- Inject a
CertificateRequestmessage into the server handshake (afterEncryptedExtensions, beforeCertificate) - Handle the client's
Certificate,CertificateVerify, andFinishedmessages - Verify the client's certificate signature using Ed25519
The patch is non-destructive: connections with verify_mode = ssl.CERT_NONE are unaffected.
Installation
pip install qh3_mutual_tls_patch
Or install from source:
pip install .
Usage
Call apply() once before creating any QUIC connections:
import ssl
from qh3_mutual_tls_patch import apply
from qh3.quic.configuration import QuicConfiguration
# Apply the patch (safe to call multiple times)
apply()
# Now you can request client certificates on the server side
config = QuicConfiguration(is_client=False)
config.verify_mode = ssl.CERT_OPTIONAL # or ssl.CERT_REQUIRED
# ... set certificate, private_key, alpn_protocols, etc.
After the handshake, the client's certificate is available via context.get_peercert().
How it works
The patch hooks three internal qh3 functions:
push_encrypted_extensions— sets a flag afterEncryptedExtensionsis writtenpush_message— intercepts the nextpush_messagecall (for the serverCertificate) to injectCertificateRequestwith its own transcript hash scope beforehand_server_handle_hello— wraps the original to restore the key-schedule hash after qh3's Finished-anticipation step, then transitions to custom states
Two custom TLS states (SERVER_EXPECT_CLIENT_CERT and SERVER_EXPECT_CLIENT_CERT_VERIFY) handle the client's response before handing control back to qh3's SERVER_EXPECT_FINISHED state.
Compatibility
- qh3 >= 1.2.1
- Python >= 3.10
Limitations
- Only Ed25519 is advertised in the
CertificateRequestsignature algorithms extension. - The patch relies on qh3 internals and may break with future qh3 releases.
License
MIT
Metadata
Release files for qh3-mutual-tls-patch 0.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| qh3_mutual_tls_patch-0.3.tar.gz | 6.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| qh3_mutual_tls_patch-0.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 13.1 kB
Release files / qh3_mutual_tls_patch-0.3.tar.gz
| Download URL | qh3_mutual_tls_patch-0.3.tar.gz |
|---|---|
| Size | 6.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a770710e866d19ad8eb75a771471500c2f4dee0a45044d5e6b4bc0950c8159dc
|
|
BLAKE2b-256 checksum How to use checksums |
ec5aaf2fd4db5b40ded1f408f8447197dcbb5a9245f66a8b74fe213517bc0169
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.15
|
Release files / qh3_mutual_tls_patch-0.3-py3-none-any.whl
| Download URL | qh3_mutual_tls_patch-0.3-py3-none-any.whl |
|---|---|
| Size | 6.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5ddc6916f9e1959b74ade16a0a567fdb27ab9ccaac6c4a41345cf3f1a497317b
|
|
BLAKE2b-256 checksum How to use checksums |
76440d1e29c72d8468cf1b4e84e5abafaa8d02260e207456e5b294a7605dfcf7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.15
|