Support for Quantum Resistant Key Exchange

Hello Syncthing Authors,

Love your work!

Go 1.24 has included support for ML-KEM-768 and 1024 (FIPS 203) in the crypto/tls since February 2025.

Per Fillipo: Post-quantum Cryptography for the Go Ecosystem Per Go: Go 1.24 Release Notes - The Go Programming Language

Any chance you can enable this quantum-resistant key encapsulation method sometime soon to meet our PQC agility goals? (i.e. ability to negotiate TLS 1.3 Group X25519MLKEM768 … ECDH + ML-KEM-768)

26> localhost:8384 -> [::1]:8384
26> Connected to localhost [[::1]:8384]
26> Verifying O = Syncthing, OU = Automatically Generated, CN = dusk-tusk
26>           DNS:myhost
26> Verification failed: [x509_verify:18] self-signed certificate
26> SSL connection succeeded
26> Peer signing digest: SHA384
26> Peer signature type: ecdsa_secp384r1_sha384
26> Negotiated TLSv1.3 group: x25519
26> Peer Temp Key: X25519, 253 bits, Security Category 0
26> Client Temp Key: X25519, 253 bits, Security Category 0
26> SSL Cipher: TLS_AES_128_GCM_SHA256, Block Cipher: id-aes128-GCM, Security Category 1
26> Certificate expiry dates:
26>   O = Syncthing, OU = Automatically Generated, CN = dusk-tusk
    Mar  4 00:00:00 2027 GMT

N.B. Security Category 0 per FIPS 203 Security Category (pp.14 nist.fips.203.pdf)

Thanks in advance!

Looks from the release notes like it’s enabled by default.

Thank you for getting back to me. Unsure of Syncthing’s setup, and yes, perhaps it’s enabled in the library, but you might have to explicitly enable ML-KEM via configuration (e.g. in nginx you use the ssl_ecdh_curve directive).

openssl s_client -groups X25519MLKEM768 -connect localhost:8384

Connecting to ::1
CONNECTED(00000200)
B84E0000:error:0A000410:SSL routines:ssl3_read_bytes:ssl/tls alert handshake failure:..\ssl\record\rec_layer_s3.c:916:SSL alert number 40
---
no peer certificate available
---
No client certificate CA names sent
Negotiated TLS1.3 group: <NULL>
---
SSL handshake has read 7 bytes and written 1466 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Protocol: TLSv1.3
This TLS version forbids renegotiation.
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---

This result means the client can’t negotiate the requested group. If I try without then I can negotiate ECDH only:

openssl s_client -connect localhost:8384

---
No client certificate CA names sent
Peer signing digest: SHA384
Peer signature type: ecdsa_secp384r1_sha384
Peer Temp Key: X25519, 253 bits
---
SSL handshake has read 930 bytes and written 1588 bytes
Verification error: self-signed certificate
---
New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256
Protocol: TLSv1.3
Server public key is 384 bit
This TLS version forbids renegotiation.
No ALPN negotiated
Early data was not sent
Verify return code: 18 (self-signed certificate)

I recently dug into this topic. While go 1.24 supports PQC by default, it doesn’t seem to work for syncthing yet.

@calmh suggested that this may be related to syncthing “targeting” an older go version while building with a newer version. Otherwise, there should be nothing to configure.

2 Likes

Thank you very much for looking into this. Your findings are the same as mine.

Oh, right, yes that’s the thing. :facepalm: So this will be enabled when 1.25 is released, or you can build yourself as you please.

1 Like