Qtum BIP-324 Pre-Authentication ECDH CPU Exhaustion
Qtum's BIP-324 v2 transport runs a pre-authentication ellswift-ECDH on every inbound connection, allowing a single source IP to saturate a core and deny honest peers.
Why this matters
The inbound peer-protocol listener (mainnet port 3888) is reachable by default on qtumd nodes. Because the asymmetric-crypto handshake occurs before any authentication or rate-limiting, a single source IP can pin one CPU core, and a small distributed fleet can measurably degrade or deny honest peers' ability to connect. This results in an availability DoS characterised by fullnode peering degradation, though it does not halt consensus (PoS block production is a separate path).
How the attack works
The attack targets the BIP-324 v2 transport responder, which is enabled by default (DEFAULT_V2_TRANSPORT{true} at src/net.h:95). When an inbound connection sends its 64-byte ellswift key, the node immediately executes Initialize (src/net.cpp:1140-1147), triggering a secp256k1 ellswift ECDH plus HKDF-SHA256 key derivation (src/bip324.cpp:41-64). This expensive cryptographic operation runs BEFORE any authentication, allowlist, per-IP rate limit, or proof-of-work gate. The only inbound cap (maxconnections=125) is soft: when full, the node calls AttemptToEvictConnection (src/net.cpp:1815) to evict an existing peer and admit the new socket. As the v2 accept path is single-threaded, a churn of fresh inbound sockets from even one source IP can saturate the path and consume CPU resources.
Affected systems
This behaviour was verified on qtumd v29.1.0 (commit 7641affd / tag v29.1, SHA256 c04e3f49…). The affected component is the P2P inbound transport (BIP-324 v2 responder). The default mainnet P2P port is 3888 (testnet 13888, regtest 23888).
Evidence
Publicly documented No CVE is assigned for this finding.
Independently reproduced by NullRabbit
The reproducer probe_qtum_bip324.py simulates the attack by generating a churn of inbound TCP connections. In "churn" mode, it opens a TCP connection, sends a 64-byte ellswift key to trigger the ECDH, and immediately closes the connection. In "hold" mode, it sends the key and holds the connection to occupy an inbound slot.
Measured under controlled conditions Loopback (isolated regtest, qtumd v29.1.0): The attack held 96.3% average / 100% median of one core over a 60-second run, achieving 14,275 handshakes/s (vs 0.3% baseline). It demonstrated approximately 39.6× egress amplification and filled all 114 inbound slots via eviction-on-full behaviour.
DigitalOcean (production-shape, 4-IP distributed attack): Honest-peer v2 handshake latency increased from a p50 baseline of 32 ms to 3371 ms (107×) under a 4-IP attack, with p99 latency reaching 9656 ms (182×). The test observed 11% outright connection denial at the 4-IP shape. A single attacker IP caused a 65× increase in p50 latency.
Inferred but not reproduced None.
Operator actions
NullRabbit recommends the following mitigations:
- Cost-gate the pre-auth crypto: Apply a per-source-IP budget, cheap proof-of-work, or connection-rate cap BEFORE the ellswift-ECDH runs to prevent unauthenticated peers from forcing unbounded asymmetric-crypto work.
- Make the v2 accept path concurrent: Modify the implementation so a single IP cannot serialise or saturate the accept path.
- Harden the inbound cap: Reserve slots for established or outbound-verified peers so that fresh-socket churn cannot evict honest peers (modifying
AttemptToEvictConnection).
Canonical references
- NRDAX Technique: NRDAX-T0205 (https://nrdax.com/techniques/NRDAX-T0205)
- Advisory: NR-2026-037
- HF Dataset:
nr-bundles-public(primitiveqtum_bip324_prehandshake_ecdh_cpu, 4 bundles) - Reproducer:
probe_qtum_bip324.py - Vendor Source: https://github.com/qtumproject/qtum
Related attacks
This finding is the same class and magnitude as the measured Bitcoin Core BIP-324 finding (BTC_V0_BIP324_PREHANDSHAKE_CPU).
Subscription call to action
Track attacks affecting qtum.
Analysis plus reproducer. No weaponised proof-of-concept code.
Related Posts
Casper P2P TLS-1.3 P-521 pre-auth ECDSA verify burn
An unauthenticated peer can force a Casper node to run a full P-521 ECDSA signature verification during TLS-1.3 handshake — before any admission gate, allowlist, or per-peer cap — burning crypto-CPU via fresh-cert-per-connection churn.
Burning go-ethereum RPC CPU with one eth_call to the BLAKE2F precompile
A single unauthenticated eth_call invoking the BLAKE2F precompile with a caller-set rounds field pins a go-ethereum RPC worker's CPU for hundreds of milliseconds from a sub-kilobyte request.
rusty-kaspa gRPC pre-auth HTTP/2 stream flood causing inbound-peering exhaustion and eviction
A pre-auth HTTP/2 stream flood on the rusty-kaspa gRPC P2P endpoint causes inbound-peering exhaustion via eviction and admission denial.
