Skip to main content

Post-quantum-aware network handshake inspector for TLS, SSH, IKE, QUIC, WireGuard, and more

Project description

quantum-sniffer

A network traffic analyzer that captures and classifies cryptographic handshakes from encrypted protocols (TLS, SSH, IPsec, WireGuard, DTLS, QUIC, DoT, STARTTLS, SMB, RDP, Kerberos, SNMPv3, OpenVPN, RADIUS, AMQP, SIP/SIPS, ZRTP, BGP, OPC-UA, and more) and tags each one as post-quantum secure, hybrid, classical, or unknown.

Status: pre-alpha. Public protocols and CLI flags may change.

Install

From source (until published to PyPI):

git clone https://github.com/jfrancis/quantum-sniffer.git
cd quantum-sniffer
pip install .
# or, for development with editable install + tests:
pip install -e '.[dev]'

Requirements: Python 3.9+, scapy. cryptography is optional and unlocks QUIC Initial-packet decryption.

After install, the quantum-sniffer console script is on $PATH. If you'd rather not install, every example below works with python3 -m quantum_sniffer … from the repo root.

Quick reference

quantum-sniffer --help                            # show all flags
sudo quantum-sniffer -o capture.jsonl -i eth0     # live capture (root required)
quantum-sniffer -o capture.jsonl -r some.pcap     # replay a saved pcap (no root)
quantum-sniffer --find-sarah-connor capture.jsonl # Skynet-readiness report

Usage

Live capture

sudo quantum-sniffer -o capture.jsonl -i eth0

Live mode requires root (or cap_net_raw on Linux: sudo setcap cap_net_raw+ep $(readlink -f $(which python3))).

Replay a saved pcap

No root needed — useful for regression testing and analyzing captures collected elsewhere.

quantum-sniffer -o capture.jsonl -r some.pcap

Flags

Required for capture/replay modes:

  • -o, --output PATH — JSONL log file (one event per line, appended). Not required when only running --find-sarah-connor.

Common flags:

  • -i, --interface IFACE — capture interface (default: scapy's default)
  • -r, --read FILE.pcap — analyze a saved capture instead of going live
  • -a, --all — include unencrypted protocols (HTTP, plain DNS, etc.)
  • --bpf "tcp port 443" — override the built-in BPF filter
  • --host 10.0.0.5 — narrow whichever filter is in effect to one host
  • -q, --quiet — write JSONL without printing each event to the console
  • --debug — re-raise analyzer exceptions instead of logging them
  • --find-sarah-connor CAPTURE.jsonl — see "Skynet readiness report" below
  • --with-skull — adds an ASCII skull to the readiness report

--interface and --read are mutually exclusive.

Post-Quantum Classification

Each event carries a post_quantum_secure field:

Status Meaning
Yes Pure post-quantum KEX/signature confirmed
Hybrid Mix of PQ and classical (transition deployment)
No Classical only — vulnerable to harvest-now-decrypt-later
Unknown Couldn't determine from observable handshake bytes

Classification is driven from explicit (group_id -> classification) tables (quantum_sniffer/pq.py), not substring matching, so novel hybrid names can't be silently misclassified.

PQ algorithms tracked include CRYSTALS-Kyber (and the standardized name ML-KEM), x25519/x448 hybrids, sntrup761x25519 (OpenSSH), and IKEv2 ML-KEM DH groups (transform IDs 35–37).

Output Format

JSON Lines, one event per line. Append-only — safe for long-running captures (the previous JSON-array format rewrote the entire file on every packet, which became O(N²) and dropped traffic on busy links).

{"protocol":"TLS","type":"TLS ClientHello","timestamp":"2026-06-10T12:34:56.789",...}
{"protocol":"WireGuard","type":"WireGuard Handshake Initiation",...}

To consume:

# As a single JSON array
jq -s . capture.jsonl

# Filter line-by-line
jq -c 'select(.post_quantum_secure == "Hybrid")' capture.jsonl

# Quantum readiness summary
jq -s 'group_by(.post_quantum_secure) | map({status: .[0].post_quantum_secure, count: length})' capture.jsonl

# CSV export
jq -r '[.timestamp, .protocol, .post_quantum_secure, .connection,
        .tls_version // .ssh_protocol_version, .selected_cipher.name // "-"]
       | @csv' capture.jsonl > report.csv

What Gets Captured

TLS / DTLS / QUIC: protocol versions, cipher suites, key exchange groups (including PQ groups like x25519kyber768), SNI, ALPN, ECH presence, session resumption flags. QUIC Initial packets are decrypted when cryptography is installed, exposing the inner TLS 1.3 ClientHello.

SSH: banner version, then KEXINIT — full algorithm negotiation lists (KEX, host-key, encryption, MAC).

IPsec/IKEv2: SA proposals walked end-to-end, including PQ DH transform IDs (ML-KEM-512/768/1024).

WireGuard: handshake message types and sizes; oversized handshakes flag possible experimental PQ variants.

Other: STARTTLS upgrades, SMB dialect, RDP/CredSSP negotiation, Kerberos etypes, SNMPv3 security level, OpenVPN control packets, RADIUS codes + EAP method, AMQP banner, SIP/SIPS, ZRTP key agreement, BGP/BGP- over-TLS, OPC-UA security policies, and a heuristic TLS detector for ~30 non-standard ports plus Tor (9001/9030/9050/9051/9150).

Skynet readiness report

--find-sarah-connor reads a JSONL capture and reports how much of the traffic would be readable by a sufficiently large quantum computer — i.e., the harvest-now-decrypt-later exposure surface, in Terminator drag.

quantum-sniffer --find-sarah-connor capture.jsonl
quantum-sniffer --find-sarah-connor capture.jsonl --with-skull

You get:

  • Counts and percentages by classification (classical / hybrid / PQ / unknown)
  • A ranked list of "high-value targets" — SNIs/IPs whose sessions were classical-only
  • Per-protocol breakdown (TLS / WireGuard / SSH / …)
  • A verdict that scales with the data ("JUDGMENT DAY IS INEVITABLE" all the way up to "HASTA LA VISTA, BABY")

This mode does not require --output and does no packet capture.

Testing

python3 -m pytest tests/

38 tests cover the bounds-check fixes in the raw TLS parser (truncated session-id / cipher-list / extensions don't crash), PQ classification, SSH KEX parsing, IKEv2 SA parsing (including ML-KEM transform IDs), the JSONL writer, CLI argument handling, and the Skynet report.

Building for PyPI

The repo ships pyproject.toml and MANIFEST.in, so:

pip install --user build twine
python3 -m build              # produces dist/*.whl + dist/*.tar.gz
python3 -m twine check dist/* # validates README + metadata
# python3 -m twine upload dist/*    # uncomment to actually publish

Limitations

  • Cannot decrypt application traffic — handshake metadata only.
  • ClientHello fragmentation across TCP segments is detected and flagged but not yet reassembled. PQ key shares often push ClientHello past one segment, so flagged events deserve attention.
  • PQ detection only catches algorithms whose IDs/names this tool knows about. New IANA assignments need updates to quantum_sniffer/constants.py and quantum_sniffer/pq.py.

Legal

Authorized use only. Monitoring networks you don't own or lack written permission to monitor likely violates the Computer Fraud and Abuse Act (US), GDPR (EU), or similar laws elsewhere.

License

GNU General Public License v3.0

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

quantum_sniffer-0.2.0.tar.gz (45.2 kB view details)

Uploaded Source

Built Distribution

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

quantum_sniffer-0.2.0-py3-none-any.whl (45.9 kB view details)

Uploaded Python 3

File details

Details for the file quantum_sniffer-0.2.0.tar.gz.

File metadata

  • Download URL: quantum_sniffer-0.2.0.tar.gz
  • Upload date:
  • Size: 45.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for quantum_sniffer-0.2.0.tar.gz
Algorithm Hash digest
SHA256 498f1268c68420270b4511c48871af74fe3ff0cc3a40e0cbe95a680c43c053ed
MD5 ee1050d2c26d44030853a6d149845993
BLAKE2b-256 1a2900a8c840d2e384d18ecd2165428494c7fd14a792e95b5cfcc168dfa7740d

See more details on using hashes here.

File details

Details for the file quantum_sniffer-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for quantum_sniffer-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d6f7591d10df7b3b98f6d3a8a35d384557d484cbef76171c8d8a4a35d8c5a1c2
MD5 7171279e7d9e3a2e944628015155a770
BLAKE2b-256 33ea64541f0f022fa540004b9a05eaf523d067ac490cf51a5797d5dd5d51cc7c

See more details on using hashes here.

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