Detect Harvest Now Decrypt Later attack patterns in network telemetry
Project description
hndl-detect
Detect Harvest Now, Decrypt Later (HNDL) attack patterns in network telemetry.
What is HNDL?
HNDL (also called "store now, decrypt later" or "retrospective decryption") is a threat model where an adversary captures encrypted network traffic today with the intent of decrypting it in the future using a cryptographically relevant quantum computer (CRQC).
The attack is straightforward:
- Intercept and store encrypted traffic that uses RSA, ECDHE, or other asymmetric key-exchange algorithms vulnerable to Shor's algorithm.
- Wait for quantum computing hardware to mature (estimated 2030-2035 for breaking RSA-2048).
- Decrypt the stored ciphertext and access the original plaintext.
HNDL is considered the most immediate quantum computing threat because the harvesting phase is happening now, before quantum computers exist. Data with long shelf lives (government secrets, medical records, financial data, intellectual property) is the primary target.
Detection challenge
Traditional HNDL detection is widely considered infeasible because the harvesting phase looks identical to normal encrypted traffic. You cannot determine intent from a packet capture. This tool does not claim to solve that problem. Instead it provides:
- Risk indicators based on traffic volume, entropy, cipher suites, connection behavior, and access patterns
- Harvest risk scoring that evaluates how attractive outbound data is to an HNDL attacker
- Patience pattern analysis that identifies slow, methodical collection behavior distinct from opportunistic exfiltration
- Honeypot/canary integration for definitive detection (the only reliable method)
- APT attribution heuristics that correlate traffic patterns against known nation-state actor signatures
What the tool detects
Signal-based detection (HNDLDetector)
Six signal types processed in real-time or batch:
| Signal | What it detects |
|---|---|
volume_spike |
Encrypted data transfers exceeding a configurable GB/hour threshold |
network_fanout |
Distributed exfiltration to many unique destinations |
long_lived_tls |
Extended TLS connections that may indicate continuous collection |
weak_cipher |
Use of quantum-vulnerable cipher suites (RSA, ECDHE, CBC, 128-bit) |
abnormal_access |
Suspicious access patterns (bulk, off-hours, sequential) |
canary_trigger |
Access to honeypot/canary resources (definitive indicator) |
Risk assessment (HNDLRiskAssessmentEngine)
Four assessment engines:
- DataValueScorer - Scores outbound data by quantum vulnerability, classification, shelf life, and volume
- PatiencePatternAnalyzer - Detects methodical, low-volume, long-duration collection patterns
- QuantumHoneypotEngine - Creates and monitors deception data for definitive HNDL confirmation
- CrossOrgCorrelator - ISAC-compatible indicator sharing and multi-organization campaign correlation
APT threat detection (HNDLThreatDetector)
Batch analysis with APT group attribution against signatures for APT28, APT29, Lazarus Group, and Equation Group. Includes quantum vulnerability assessment and STIX-format threat intelligence export.
Installation
pip install hndl-detect
Or from source:
git clone https://github.com/ScrappinR/hndl-detect.git
cd hndl-detect
pip install -e .
CLI usage
The CLI reads JSONL (one JSON object per line) from stdin or a file.
Signal detection mode
# From file
hndl-detect --input flows.jsonl
# From stdin
cat flows.jsonl | hndl-detect
# With custom thresholds
hndl-detect -i flows.jsonl --volume-threshold 5.0 --fanout-threshold 10
# Pretty-printed output
hndl-detect -i flows.jsonl --format pretty
Risk assessment mode
hndl-detect -i flows.jsonl --mode risk --format pretty
Input format
Each line is a JSON object representing a network flow:
{
"timestamp": "2025-01-15T14:30:00Z",
"source_ip": "10.0.1.50",
"destination_ip": "203.0.113.10",
"port": 443,
"protocol": "TCP",
"bytes_sent": 15000000000,
"bytes_received": 500000,
"duration_seconds": 3600,
"tls_version": "TLS 1.2",
"cipher_suite": "TLS_RSA_WITH_AES_128_CBC_SHA",
"entropy": 7.8,
"packet_count": 12000
}
Supported field aliases: src_ip/source_ip, dst_ip/dest_ip/destination_ip, bytes/bytes_sent/byte_count.
Output format
Each alert is a JSON object with threat details:
{
"threat_id": "a1b2c3d4-...",
"severity": "high",
"confidence": 0.72,
"threat_type": "volume_spike",
"detected_at": "2025-01-15T14:30:05Z",
"source_ip": "10.0.1.50",
"destination_ips": ["203.0.113.10"],
"data_volume_bytes": 15000000000,
"indicators": {"gb_per_hour": 14.0, "entropy": 7.8},
"recommendations": ["Investigate source for unauthorized data collection", "..."]
}
Library usage
from datetime import datetime, timezone
from hndl_detect import HNDLDetector, NetworkSignal, DetectionThresholds
# Create detector with custom thresholds
detector = HNDLDetector(
thresholds=DetectionThresholds(
volume_threshold_gb=5.0,
fanout_threshold=10,
entropy_threshold=7.5,
)
)
# Process a network signal
signal = NetworkSignal(
timestamp=datetime.now(timezone.utc),
source_ip="10.0.1.50",
destination_ip="203.0.113.10",
port=443,
protocol="TCP",
bytes_sent=15_000_000_000,
bytes_received=500_000,
duration_seconds=3600.0,
tls_version="TLS 1.2",
cipher_suite="TLS_RSA_WITH_AES_128_CBC_SHA",
entropy=7.8,
packet_count=12000,
)
threat = detector.process_network_signal(signal)
if threat:
print(f"Threat detected: {threat.threat_type} (severity={threat.severity.value})")
Risk assessment
from datetime import datetime, timezone, timedelta
from hndl_detect import HNDLRiskAssessmentEngine, NetworkFlow
engine = HNDLRiskAssessmentEngine()
flow = NetworkFlow(
flow_id="flow-001",
source_ip="10.0.1.50",
dest_ip="203.0.113.10",
source_port=49152,
dest_port=443,
protocol="TCP",
bytes_transferred=5_000_000_000,
packet_count=50000,
start_time=datetime.now(timezone.utc) - timedelta(hours=1),
end_time=datetime.now(timezone.utc),
encrypted=True,
cipher_suite="TLS_RSA_WITH_AES_128_GCM_SHA256",
payload_entropy=7.8,
data_type_hints=["financial"],
)
result = engine.assess_flow(flow)
print(f"Risk: {result['risk_assessment']['overall_risk']}")
print(f"Score: {result['risk_assessment']['risk_score']:.2f}")
Dependencies
None. This package uses only the Python standard library.
Limitations
- HNDL detection from network traffic alone cannot determine attacker intent. All detections are risk indicators, not confirmations.
- Definitive HNDL detection requires honeypot/canary deployment and monitoring for exfiltration of planted data.
- APT attribution is heuristic-based and should be treated as a starting point for investigation, not a conclusion.
- Thresholds must be tuned for your environment. Default values are conservative.
License
Apache License 2.0. See LICENSE for details.
Author
Brian James Rutherford (brian@delalli.com)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hndl_detect-0.1.0.tar.gz.
File metadata
- Download URL: hndl_detect-0.1.0.tar.gz
- Upload date:
- Size: 43.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6dfa3ca2e5db80ff193a5a9434fcac2fea531b76622841e888af380a1c213de6
|
|
| MD5 |
8a9bc4aab0ed0b08fa3aa2a0dd14cd30
|
|
| BLAKE2b-256 |
44a722aedcefa3893c498e14fe2da026b1274158eb6b3f3281fb6a9d9baef22a
|
File details
Details for the file hndl_detect-0.1.0-py3-none-any.whl.
File metadata
- Download URL: hndl_detect-0.1.0-py3-none-any.whl
- Upload date:
- Size: 39.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9fb80a9495167b78c62fbb44c45e84e373c656c91cc3687c0b5dd0c0669c13f5
|
|
| MD5 |
a4f28d5e60fee03276146f616fa7c4b1
|
|
| BLAKE2b-256 |
0202a505eef360f87cccd9126ee51172d7ca6d25c51166a3173c3a2b9b1fc74f
|