velocity/1: Why TLS 1.3 + QUIC isn't enough for the post-quantum era
Harvest-now-decrypt-later attacks make today's handshakes a liability. Here's the threat model behind Project Velocity and how hybrid crypto addresses it.
The problem TLS 1.3 + QUIC doesn't solve
TLS 1.3 is a well-engineered protocol. QUIC is a well-engineered transport. Together they cut connection latency, eliminate head-of-line blocking, and survive NAT rebinds without a full handshake. They are, by most measures, the best widely-deployed secure transport stack we have.
That's exactly why the timing matters.
A nation-state or well-resourced attacker who can't break X25519 today can still record encrypted traffic at scale and wait. When a cryptographically relevant quantum computer becomes available — current NIST estimates put that window somewhere in the 2030s, though the uncertainty bands are wide — all that archived traffic becomes readable. This is the harvest-now-decrypt-later (HNDL) threat, and it is not theoretical: NSA programs like PRISM already demonstrated the appetite and infrastructure to collect at scale.
For personal banking traffic, HNDL is probably not your problem. For health records, infrastructure credentials, or long-lived secrets that need to stay private for fifteen years, it is a serious engineering constraint today.
TLS 1.3 with a classical X25519 key exchange offers no protection against this. QUIC inherits the same limitation. The protocol is excellent; the primitives have an expiry date.
What Velocity adds
Project Velocity is a UDP-based transport protocol I've been building as a post-quantum successor to the TLS 1.3 + QUIC stack. The ALPN identifier is velocity/1. The design philosophy is: hybrid everything, degrade gracefully, measure honestly.
Hybrid key exchange
The handshake combines X25519 with ML-KEM (the NIST-standardized version of Kyber). Both run in parallel; the session key is derived from the concatenation of both shared secrets. An attacker must break *both* classical Diffie-Hellman *and* the lattice-based problem simultaneously to recover the key.
// velocity-crypto: key schedule sketch
let classical_secret = x25519(our_private, their_public);
let pq_secret = ml_kem_decapsulate(&ciphertext, &our_kem_private);
let ikm = [classical_secret.as_bytes(), pq_secret.as_bytes()].concat();
let session_key = hkdf_expand(&ikm, b"velocity/1 session key", 32);
The hybrid construction means Velocity is strictly at least as secure as X25519 alone, even if ML-KEM later turns out to have a weakness. This is the correct conservative posture during the transition period.
Hybrid signatures
Authentication uses Dilithium (ML-DSA) combined with ECDSA. Both signatures must be valid; both must fail for an attacker to forge a certificate. The certificate format extends the existing X.509 SubjectPublicKeyInfo field to carry dual algorithm identifiers — ugly but interoperable with existing PKI tooling that ignores unknown extensions.
0-RTT and ECH
Velocity supports ticket-based 0-RTT resumption with replay protection. Servers maintain a one-time-use bloom filter per session window; replayed early-data packets are dropped before they reach application logic.
Encrypted Client Hello (ECH) is supported via DNS SVCB records. The server's public key is published in DNS, the client encrypts the SNI before the first packet hits the wire, and a passive observer sees only the ECH outer name — not the actual destination. This matters for metadata privacy independently of content encryption.
Graceful HTTP/3 fallback
Not every network path will accept velocity/1. Corporate proxies, restrictive firewalls, and legacy middleboxes will be a reality for years.
Velocity handles this through ALPN negotiation. The client advertises ["velocity/1", "h3"] in order. If the server supports Velocity, it picks velocity/1 and the handshake proceeds with the full hybrid stack. If only HTTP/3 is available, the connection falls back to h3 transparently — you get QUIC's transport benefits without the PQ crypto layer. If even QUIC is blocked, the application layer can fall back further to TCP-based TLS 1.3.
The fallback isn't a security hole; it's an honest acknowledgment that a working connection is better than no connection, and that the threat model doesn't uniformly require PQ guarantees on every path today.
Performance reality check
Hybrid handshakes are more expensive than classical ones. ML-KEM adds CPU cycles; Dilithium signatures are larger than ECDSA signatures. These are real costs.
Criterion benchmarks on a Ryzen 7950X show in-memory handshake parsing at roughly 0.08 µs, compared to a TLS 1.3 baseline of around 1.1 ms for a full round-trip. The delta comes from the additional lattice operations, though most of that cost is dominated by network round-trips in practice rather than CPU time.
CBOR framing for protocol messages cuts payload overhead approximately 3× versus the JSON framing some earlier drafts used. For a handshake that's already adding bytes for dual key material and dual signatures, keeping the framing tight matters.
Where the project is now
Velocity 0.9.1 is in the Prototype stage. The repository contains five Rust crates (velocity-core, velocity-crypto, velocity-server, velocity-client, velocity-ssh-bridge), an RFC-style specification draft with byte-accurate transcripts, and formal security models in Tamarin/ProVerif that verify mutual authentication and forward secrecy properties.
The ssh-bridge crate (vshd, vsh-proxy) is a side project I find genuinely useful: it replaces SSH's classical key exchange with the Velocity handshake, so interactive sessions get the same HNDL protection as HTTPS traffic.
This is research infrastructure, not production software. But the design choices are defensible, the threat model is real, and the hybrid approach is exactly what NIST recommended when it published the first PQ standards in 2024. The question isn't whether to care about harvest-now-decrypt-later — it's whether to start caring before the harvest has already happened.