# Adding a post-quantum hybrid handshake to a Rust VPN

> Source: <https://dev.to/alexandr_litvinov/adding-a-post-quantum-hybrid-handshake-to-a-rust-vpn-pk8>
> Published: 2026-06-18 22:13:48+00:00

I maintain [Qeli](https://github.com/litvinovtd/qeli), a self-hosted VPN whose core and server are written in Rust. For the 0.7.x line I added a **hybrid post-quantum key exchange** to the inner handshake, and wired the same primitive into the non-Rust clients. Here is how it is built and what bit me.

The threat is "harvest now, decrypt later": traffic captured today, decrypted once a large quantum computer exists. Classical X25519 does not survive that; pure ML-KEM is young, and I do not want one new primitive to be the only thing between you and plaintext. So the handshake runs **both** and mixes the results - you are safe unless *both* X25519 and ML-KEM-768 fall.

Mixing both secrets in the KDF (instead of picking one) is what makes it hybrid: an attacker has to break *both* to recover the key.

Qeli has native clients on Windows/macOS (C#) and Android (Kotlin). Rather than reimplement ML-KEM three times, the Rust implementation is the single source of truth, and the other clients call into a small native core over **FFI** (C#) and **JNI** (Android). Same wire format everywhere, and the PQ code gets reviewed once.

Code is open (AGPL-3.0 core, MPL-2.0 clients): [https://github.com/litvinovtd/qeli](https://github.com/litvinovtd/qeli) - and there is a project site at [https://qeli.ru](https://qeli.ru). Feedback on the handshake and transport code is very welcome.
