Skip to main content

Probe a server's TLS configuration and post-quantum (ML-KEM) key-exchange readiness

Project description

pqcprobe

Tests Lint & Security CodeQL Python versions License: MIT

A small command-line TLS probing utility that uses pyOpenSSL to inspect an HTTPS server's TLS configuration, with a focus on post-quantum readiness.

Features:

  • Reports negotiated TLS version, cipher, ALPN and certificate summary
  • Reports the negotiated key-exchange group and flags whether it is post-quantum (e.g. X25519MLKEM768) or classical
  • Assesses post-quantum posture: enumerates which key-exchange groups the server accepts and flags "harvest-now, decrypt-later" (HNDL) risk when no post-quantum key exchange is offered
  • Verifies the certificate matches the requested hostname (SAN/CN, wildcard and IP aware)
  • Probes server support for TLS 1.3 and TLS 1.2
  • Samples which TLS 1.2 ciphers the server accepts (and attempts TLS 1.3 ciphersuites where supported by OpenSSL)
  • Can fetch raw PEM for the server certificate (--raw-cert)
  • Concurrency option for probing (--concurrency)
  • Human-friendly summary (--pretty) or JSON output (--json)
  • Meaningful exit codes for scripting (see below)

Requirements:

  • Python 3.9.2+
  • pyOpenSSL, cryptography (installed automatically)
  • OpenSSL 3.x recommended (3.5+ for post-quantum group support). On macOS the system openssl is LibreSSL and cannot test the ML-KEM hybrid groups; install OpenSSL 3.5+ (e.g. via Homebrew) for full functionality.

Install

pip install pqcprobe

This installs a pqcprobe command. To run from a source checkout instead:

python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install -e .

Usage

pqcprobe https://example.com --pretty
pqcprobe example.com:443 --json
pqcprobe example.com:443 --raw-cert

# Post-quantum audit: fail (exit 3) if the server offers no PQC key exchange
pqcprobe https://example.com --fail-on-classical-only
# Skip group probing entirely (e.g. when the openssl CLI is unavailable)
pqcprobe https://example.com --no-groups

(From a source checkout without installing, use python3 pqcprobe.py ....)

Post-quantum key-exchange probing:

  • Enumerating group support forces individual groups via the native openssl CLI, since pyOpenSSL does not expose a way to set the group list. OpenSSL 3.5+ is required for the ML-KEM hybrid groups (X25519MLKEM768, etc.). Groups the local openssl doesn't recognize are reported as "not testable" rather than "unsupported" (relevant on macOS, whose system openssl is LibreSSL).
  • Reading the negotiated group uses pyOpenSSL's Connection.get_group_name() and needs no external tools.

Exit codes:

  • 0 success
  • 1 handshake failed
  • 2 certificate hostname mismatch (when verifying)
  • 3 no post-quantum key exchange offered (only with --fail-on-classical-only)

Notes:

  • Programmatic overriding of TLS 1.3 ciphersuites requires a recent OpenSSL + pyOpenSSL exposing set_ciphersuites.
  • Cipher probing may produce handshake failures for many ciphers — the tool records successes and errors.
  • Only use pqcprobe against systems you own or are authorized to test.

Contributing

Contributions are welcome — see CONTRIBUTING.md. Security issues should be reported privately per SECURITY.md.

License

MIT © Andre Van Klaveren

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pqcprobe-0.1.0.tar.gz (25.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pqcprobe-0.1.0-py3-none-any.whl (13.9 kB view details)

Uploaded Python 3

File details

Details for the file pqcprobe-0.1.0.tar.gz.

File metadata

  • Download URL: pqcprobe-0.1.0.tar.gz
  • Upload date:
  • Size: 25.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pqcprobe-0.1.0.tar.gz
Algorithm Hash digest
SHA256 ac5739f63fcb7de031b1cf08b390599ff3b8fd8739bfc4464644451b944c2772
MD5 4e0493a04966265f1df84e5375aa502c
BLAKE2b-256 40860c1a532ec02a0bde78b19129f2ee2eb7f5134793f4b39390c4db496315ae

See more details on using hashes here.

Provenance

The following attestation bundles were made for pqcprobe-0.1.0.tar.gz:

Publisher: publish.yml on opratr/pqcprobe

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pqcprobe-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: pqcprobe-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 13.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pqcprobe-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e5b8c049952955bbfaf8d8ba7b280ea4657f2a45c926c5dde2ef459343c9f6a2
MD5 366d5c6621adff753588fd73cdbdc132
BLAKE2b-256 0bf01a139d87fa95ca63ee2032bbb332f3811122bc1f81b7e6e893e16476f83d

See more details on using hashes here.

Provenance

The following attestation bundles were made for pqcprobe-0.1.0-py3-none-any.whl:

Publisher: publish.yml on opratr/pqcprobe

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page