Post-quantum Xray: 14 questions about VLESS Encryption and ML-DSA-65 in REALITY

In other Xray configs, two new entities appear more and more often: the string "decryption": "mlkem768x25519plus.native.600s..." instead of the familiar "none", and a pair of fields mldsa65Seed / mldsa65Verify inside realitySettings. Both appeared recently, both are about post-quantum cryptography, and both solve different problems — which is why chats regularly advise “turn it on, it’s quantum encryption,” without explaining what exactly it protects against.

I’ve collected answers to the questions that are asked most often. The bill—taken from Project X documentation and the description of the PR that brought this mechanism.

Info:

Who will find this useful: those who run their server on Xray-core (including under panels like Remnawave, Marzban, 3x-ui) and distribute configs further. If you’re only a client and you were given keys — questions 4, 7 and 13 will be useful to you.


1. What exactly was added and when

The mechanism arrived in Xray-core via pull request #5067 — “VLESS protocol: Add lightweight, Post-Quantum ML-KEM-768-based PFS 1-RTT / anti-replay 0-RTT AEAD Encryption” by RPRX. In the release notes for v26.6.1 (June 1, 2026), “VLESS Post-Quantum Encryption” is listed as a separate item with a link to this PR.

At the same time, REALITY gained fields mldsa65Seed (server) and mldsa65Verify (client) — this is about signatures, not encryption. The difference between them is half the confusion around the topic, and we’ll return to it in question 10.

2. Doesn’t REALITY already encrypt traffic?

It does encrypt, but it is not responsible for what people usually think.

REALITY is primarily a matter of masking and authenticating the server. The client sends a real TLS ClientHello with a SNI of a third-party site, the server presents a certificate for that site, and for DPI the picture looks like a normal visit to example.com. Inside is X25519, a short identifier shortId, and a check that the server really is yours, not a man-in-the-middle.

What REALITY is not required to do — protect you from the consequences of leaking a client config. That gap is closed by VLESS Encryption.


Diagram based on xtls.github.io documentation and PR XTLS/Xray-core#5067

3. What does VLESS Encryption protect against and what REALITY does not

The scenario explicitly analyzed in the PR description: the client config leaks somewhere. You sent a vless:// link in a messenger, copied it via clipboard on a phone with a “smart” keyboard, pasted it into a cloud note, gave it to a friend — many variants.

With the old scheme ("decryption": "none") the owner of such a config gets everything: they can connect, they can — if they also captured your traffic — decrypt what was recorded, they can stand in the middle. With VLESS Encryption, the key of each connection is derived from an ephemeral ML-KEM-768 + X25519 key pair generated on the spot, and cannot be reconstructed from the config contents.

Important:

The main idea in one line: REALITY answers the question “what does it look like from the outside and is this the right server,” VLESS Encryption — the question “what happens if the connection string ends up in someone else’s hands.”

In the PR description, this is broken down into two levels. The NFS layer (non-forward-secret) is built on pre-known public keys and is needed so intermediate nodes in the chain cannot impersonate the server. The PFS layer negotiates temporary keys for each connection — and even if the server private key is leaked, you cannot decrypt past traffic. For comparison, the same section explicitly mentions Shadowsocks 2022 / AEAD and VMess: they rely on a fixed PSK and forward secrecy does not apply in this sense.

4. What does “post-quantum” mean if there is no quantum computer yet

The threat is not “will be broken tomorrow,” but a phenomenon of harvest now, decrypt later: traffic is recorded today and decrypted years later when a suitable machine appears. For a messenger this is not urgent, for a person whose traffic is being archived by someone, the question is open.

ML-KEM-768 is a standardized NIST key encapsulation mechanism (FIPS 203, originally CRYSTALS-Kyber). In mlkem768x25519plus it is used alongside the classic X25519, not instead of it: the hybrid only breaks if both halves are broken. This is the same logic by which browsers have been using X25519MLKEM768 in TLS for several years.

Warning:

Be realistic: the post-quantum part does not make you invisible to DPI, does not speed up the connection, and does not solve any current censorship issues. It is cheap and hedges against a hypothetical scenario. If someone is selling you a “quantum VPN” as a bypass – you’re being sold marketing.

5. How to read this long string

The format is blocks separated by dots, in a fixed order. The same grammar applies to the server decryption and the client encryption, only the third block and the trailing key content differ.


Diagram based on VLESS(XTLS Vision Seed) | Project X and PR XTLS/Xray-core#5067

Block Server (decryption) Client (encryption)
1. Handshake mlkem768x25519plus same, must match
2. Appearance native / xorpub / random same, must match
3. Session ticket lifetime: 600s or range 100-500s 0rtt or 1rtt
4. Padding 100-111-1111 — min-max probability same
5. Delay 75-0-111 — “wait 75% of 0…111 ms” same
6. Padding 50-0-3333 same
7. X25519 private key password (server public key)
8. ML-KEM-768 Seed client part

If blocks 4–6 are omitted, defaults apply: 100-111-1111.75-0-111.50-0-3333.

6. native, xorpub or random — which to choose

Mode What it does When to pick
native Hides nothing: headers look like TLSv1.3 AEAD, public keys are recognizable Within REALITY/TLS, where the outer layer already provides the look
xorpub XORs away the telltale signs of ML-KEM-768 and X25519 public keys When VLESS Encryption works without TLS on top
random Full randomization via XOR (AES-256-CTR). According to the PR it affects ~0.006% of traffic Maximum inconspicuousness when there are no wrappers at all

The PR description separately notes that the pair native/xorpub + XTLS ReadV/Splice provides better performance because there is no need to encrypt over already encrypted data. So if you have REALITY + Vision — native here is not a “weak option,” but a consciously correct one.

7. 0-RTT — savings or a hole

0rtt allows the client to reuse a previously issued ticket and skip the full handshake: the first data message goes immediately. 1rtt always performs a full exchange.

Protection against replay here is done by the ticket lifetime on the server side (default about 10 minutes), not by clock skew checking between client and server. Practical difference: you don’t need to worry about clock desynchronization on routers or phones — the common pain of Shadowsocks-AEAD and old schemes with maxTimeDiff.

Note:

Padding and delays (blocks 4–6) apply only to 1-RTT handshakes. If you have 0rtt and tickets live, you will not see these blocks for most connections.

8. How to generate keys

The quickest path is one command that immediately outputs a consistent pair of strings for the server and client:

./xray vlessenc

Manual path if you want to control each block:

./xray x25519      # X25519 pair: PrivateKey for the server, Password for the client
./xray mlkem768    # Seed for the server and client part
./xray uuid        # User UUID, if you’re creating a new one

shortIds for REALITY are hex of even length, up to 8 bytes (16 hex characters) inclusive.

9. How a working config looks

Server inbound — VLESS with Vision on top of XHTTP and REALITY:

{
  "listen": "0.0.0.0",
  "port": 443,
  "protocol": "vless",
  "settings": {
    "clients": [
      { "id": "<UUID>", "flow": "xtls-rprx-vision" }
    ],
    "decryption": "mlkem768x25519plus.native.600s.<X25519 PrivateKey>.<ML-KEM-768 Seed>"
  },
  "streamSettings": {
    "network": "xhttp",
    "security": "reality",
    "realitySettings": {
      "target": "example.com:443",
      "serverNames": ["example.com"],
      "privateKey": "<REALITY PrivateKey>",
      "shortIds": ["0123456789abcdef"]
    },
    "xhttpSettings": { "path": "/<случайный путь>" }
  }
}

Client side is mirrored:

{
  "protocol": "vless",
  "settings": {
    "vnext": [{
      "address": "<ваш IP или домен>",
      "port": 443,
      "users": [{
        "id": "<UUID>",
        "flow": "xtls-rprx-vision",
        "encryption": "mlkem768x25519plus.native.0rtt.<X25519 Password>.<ML-KEM-768 Client>"
      }]
    }]
  }
}
Error:

The field decryption must not be left empty. If encryption is not needed, explicitly write "none". An empty string is not “disabled”; it is an invalid config, and Xray will crash on startup.

10. So what are mldsa65Seed and mldsa65Verify

This is no longer about channel encryption, but about the certificate signature with which REALITY presents itself to the client.

  • mldsa65Seed on the server — private key to which a second post-quantum signature is added to the certificate using ML-DSA-65 (FIPS 204).
  • mldsa65Verify on the client — public part that verifies this signature.

Reason: server authentication in REALITY historically relied on X25519, and it is broken by the same hypothetical quantum adversary. ML-DSA-65 adds a parallel mechanism that is not broken by such an adversary. If the field is not filled — the old scheme works, as before.

Warning:

Hidden pitfall from the documentation: when hybrid exchange X25519MLKEM768 is enabled, the certificate of your target must be larger than 3500 bytes. Post-quantum keys and signatures are bulky, and an overly small certificate for someone else’s site breaks things. If the connection starts to fail after enabling it, start troubleshooting here rather than with the keys.

11. REALITY fields reference — what’s there at all

Field Side Purpose
target server Where traffic goes that failed verification, e.g. example.com:443
serverNames server Acceptable SNI values; empty string allows connections without SNI
privateKey server Private X25519 key (./xray x25519)
shortIds server List of short identifiers, hex of even length up to 16 characters
minClientVer server Minimum client version, defaults to 26.3.27; lowering it is not recommended — older clients are more noticeable for DPI
maxClientVer server Maximum client version
maxTimeDiff server Allowable clock skew in milliseconds
mldsa65Seed server Post-quantum certificate signature (ML-DSA-65)
limitFallbackUpload / limitFallbackDownload server Bandwidth limit for traffic that went to fallback
serverName client One of the server’s serverNames values
fingerprint client Required. uTLS profile, e.g. chrome
shortId client One of the server’s shortIds, may be empty
password client Server’s public X25519 key
mldsa65Verify client Verification of the post-quantum signature
spiderX client Starter path for the crawler; better to vary it for different clients

The analysis of the REALITY mechanism itself is in a separate topic: Guide: how Reality (XTLS) works and why it bypasses DPI.

12. How fast is it really

The PR description provides two arguments. First: VLESS Encryption does not have a separate AEAD length field, which yields about a 10% win relative to Shadowsocks 2022. Second: with XTLS enabled, re-decrypting proxied TLSv1.3 does not happen at all — on Linux, a kernel-level splice is used, and traffic goes nearly at native speed.

Separately noted is the packet size limit — 8K, later 16K, introduced to avoid unnecessary buffering.

Note:

These are the author’s figures from the PR description, not independent benchmarks. Test on your hardware: on a weak ARM router, post-quantum handshake is noticeably heavier than classic X25519, and with a high number of short connections the difference is visible.

13. What will break for clients

The main risk is not cryptography, but compatibility. The encryption string is a kernel-level field in Xray, and a client that does not understand it simply won’t connect. Community discussions directly recommend keeping a separate inbound with the classical scheme vless + vision + reality for such users.

Practical steps:

Success:
  1. Bring up a second inbound with VLESS Encryption on a separate port, without touching the working one.
  2. Check your clients against it one by one, noting the Xray kernel version, not the GUI wrapper — they differ.
  3. Ensure the target certificate is larger than 3500 bytes if you enable mldsa65.
  4. Only after that migrate users and shut down the old inbound.

Separately: mlkem768x25519plus is an Xray-core construct. Do not port the line to another core’s config “by analogy”; if you have clients on sing-box or mihomo, refer to their own documentation and do not treat support as given. We have a layer-by-layer breakdown of routing in sing-box.

14. Turn it on now or wait

Thoughtfully: turning it on makes sense if you are distributing configs to people who will definitely forward them in a messenger. This scenario provides real gains today — regardless of when or whether a quantum computer will appear at all.

There is no point in rushing if you have a mixed zoo of clients you don’t control and no one to support updates. Breaking working reliability for protection against a hypothetical threat is a bad deal.

And a general caveat that applies to any tunnel: everything described protects the channel up to your server. What happens after the server, and what you send to another service over this channel, neither ML-KEM nor ML-DSA fix.

If something in the chain still doesn’t work, there is a separate guide “symptom → cause → what to do”.


Sources

Question:

Have you already migrated your users to mlkem768x25519plus — or do you keep the classic for compatibility? I’m interested in numbers: how many clients dropped off when switching and on what hardware post-quantum handshake is noticeable on CPU.