-
Notifications
You must be signed in to change notification settings - Fork 147
Description
In TLS 1.3, the cipher suite name (e.g. TLS_AES_128_GCM_SHA256) no longer encodes the key exchange mechanism — it is negotiated separately via the supported_groups extension. tlsx currently reads ConnectionState.Version and
ConnectionState.CipherSuite but does not read ConnectionState.CurveID, so the negotiated key exchange is not reported.
Since Go 1.24, ConnectionState.CurveID is populated after the handshake. A new field like key_exchange in the JSON output would expose this value (e.g. X25519MLKEM768, X25519, CurveP256).
Suggested change in the ctls client (pkg/tlsx/tls/tls.go) — read connectionState.CurveID alongside the existing Version and CipherSuite reads, and add a corresponding field to the Response struct in
pkg/tlsx/clients/clients.go:
KeyExchange string json:"key_exchange,omitempty"
Describe the use case of this feature:
NIST/IEFT post-quantum cryptography standards (FIPS 203 / ML-KEM) are being deployed in production. Chrome and Cloudflare already negotiate X25519MLKEM768 (CurveID 4588) by default in TLS 1.3 handshakes.
Security teams need to audit which hosts in their environment support post-quantum key exchange and which are still using classical-only key agreement. Without the key exchange group in tlsx output, there is no way to distinguish a PQ-secured connection from a classical one — both report the same cipher suite name.
This would also be useful for detecting servers that only support older curves (e.g. CurveP256 without X25519) or for general TLS configuration auditing beyond cipher suites.