Post-quantum cryptography (PQC) is no longer a “someday” topic. Standards are published, vendors are shipping hybrid TLS key exchange groups, and security teams are being asked a deceptively simple question:
Are we actually negotiating PQC (or hybrid PQC) on real connections—outside the lab?
pqcreader is a small Python package that wraps Python requests calls and exposes TLS handshake metadata—especially the negotiated key exchange group (where hybrid PQC shows up) and the cipher suite.
PyPI: https://pypi.org/project/pqcreader/
Source repo: https://github.com/ConnectingApps/PyPqcReader
PQC in two minutes: why it matters
“Harvest now, decrypt later”
Even before large-scale quantum computers exist, attackers can record encrypted traffic today and attempt to decrypt it later when they do. If the data has a long confidentiality lifetime (think: customer data, credentials, health data, intellectual property, state secrets), that risk is practical rather than academic.
NIST has finalized initial post-quantum encryption standards
In 2024, NIST finalized its first post-quantum encryption standards, including FIPS 203 (ML-KEM) (derived from CRYSTALS-Kyber and renamed ML-KEM).
NIST announcement: https://www.nist.gov/news-events/news/2024/08/nist-releases-first-3-finalized-post-quantum-encryption-standards
TLS migration reality: hybrid key exchange
Most deployments won’t jump directly from “classical-only” to “PQC-only.” The common path is hybrid key exchange: combine classical ECDHE with a post-quantum KEM so that the handshake remains secure even if one component becomes vulnerable.
IETF hybrid TLS design draft: https://datatracker.ietf.org/doc/draft-ietf-tls-hybrid-design/
What pqcreader does
pqcreader focuses on a very operational capability:
- Wrap an HTTP request (via
requests) - Extract TLS handshake details that are not typically easy to retrieve from standard Python APIs
- Print the negotiated group and cipher suite
This is especially useful when testing hybrid PQC deployments, where the negotiated group can be the difference between “we think it’s enabled” and “it is actually happening on the wire.”
OpenSSL (example of hybrid groups such as X25519MLKEM768): https://docs.openssl.org/3.6/man3/SSL_CTX_set1_curves/
⚠️ Important constraints
The project states (verbatim):
⚠️ IMPORTANT: This library is Linux-only. It will NOT work on Windows, macOS, or any other operating system. The library uses Linux-specific OpenSSL library loading and relies on system-level integration that is not available on other platforms. Please ensure you are running on a Linux system before attempting to use this library.
In addition, it is CPython-only and described as experimental across Python/OpenSSL variants. In practice, you should treat pqcreader as a diagnostic probe (CI checks, rollout validation, troubleshooting), not as a core production dependency.
Installation
pip install pqcreader
Requirements (from the project)
- Python 3.10+
- Linux operating system (required for OpenSSL tracing)
- OpenSSL 3.x
Quick start: trace a real requests.get()
Basic usage (from the README)
import requests
from pqcreader import pqcreader_request
# Wrap any requests call
response, tls_trace = pqcreader_request(
lambda: requests.get("https://www.google.com", timeout=10)
)
print(f"Status: {response.status_code}")
print(f"Negotiated Group: {tls_trace.group}")
print(f"Cipher Suite: {tls_trace.cipher_suite}")
What you’re looking for
If your client, server, and OpenSSL runtime negotiate a hybrid PQC group, the group name is typically where you’ll see it. Hybrid group names are ecosystem-specific, but OpenSSL documentation includes examples like X25519MLKEM768.
OpenSSL curves/groups doc (includes hybrid group examples): https://docs.openssl.org/3.6/man3/SSL_CTX_set1_curves/
These helpers are useful for quick probes you can drop into:
- CI smoke tests (to detect negotiation regressions)
- environment verification during rollout (dev/staging/prod)
- incident response diagnostics (confirm crypto posture quickly)
How it works (high level)
The package intercepts HTTPS connections (via urllib3 under requests), accesses the underlying OpenSSL socket, and queries OpenSSL for handshake metadata.
This is a practical approach for answering the one question that matters operationally:
“What did we negotiate for this request, in this environment, at runtime?”
Where pqcreader fits in a PQC readiness workflow
A pragmatic engineering workflow for PQC readiness looks like this:
Standards awareness: understand what is being standardized and deployed (e.g., ML-KEM).
https://www.nist.gov/news-events/news/2024/08/nist-releases-first-3-finalized-post-quantum-encryption-standardsProtocol design: understand hybrid TLS 1.3 construction and expected negotiation behavior.
https://datatracker.ietf.org/doc/draft-ietf-tls-hybrid-design/Runtime verification: confirm what is negotiated by your real clients and endpoints.
That is wherepqcreaderprovides immediate value.
Links
-
pqcreaderon PyPI: https://pypi.org/project/pqcreader/ - Source repository: https://github.com/ConnectingApps/PyPqcReader
- NIST PQC standards announcement: https://www.nist.gov/news-events/news/2024/08/nist-releases-first-3-finalized-post-quantum-encryption-standards
- IETF hybrid TLS design draft: https://datatracker.ietf.org/doc/draft-ietf-tls-hybrid-design/
- OpenSSL groups/curves documentation (hybrid examples): https://docs.openssl.org/3.6/man3/SSL_CTX_set1_curves/
If you want, Mr Acohen, I can also format it to dev.to conventions (front matter, recommended tags, and a tighter opening hook) while keeping the “direct links only” rule and keeping every README code block intact.
Top comments (0)