Go (crypto/tls)
Is PQC enabled? — quick check
macOS / Linux / Windows
# 1) No-dependency check — identify this machine first.
uname -a 2>/dev/null || true
# 2) Dependency check — prompt before installing anything.
if ! command -v go >/dev/null 2>&1; then
echo 'Go was not found.'
printf 'Install or enable Go now? [y/N] '
read answer
case "$answer" in
[Yy]*) echo 'Install Go 1.23+ from your OS package manager or go.dev, then rerun this snippet.' ;;
*) echo 'Skipping Go-based check.'; exit 1 ;;
esac
fi
go version
# Quick inline probe — Go 1.23+ negotiates X25519MLKEM768 by default
# when the server offers it. The connection state exposes the group.
cat <<'EOF' | go run -
package main
import ("crypto/tls"; "fmt")
func main() {
c, err := tls.Dial("tcp", "example.com:443", &tls.Config{ServerName: "example.com"})
if err != nil { fmt.Println("err:", err); return }
defer c.Close()
s := c.ConnectionState()
fmt.Printf("tls=%x cipher=%s curveID=%d\n",
s.Version, tls.CipherSuiteName(s.CipherSuite), s.CurveID)
}
EOF Expected when PQC is ON
go version go1.23.4 darwin/arm64
tls=304 cipher=TLS_AES_128_GCM_SHA256 curveID=4588
# 4588 = 0x11EC = X25519MLKEM768 What you'll see when PQC is OFF
go version go1.22.6 linux/amd64
tls=304 cipher=TLS_AES_128_GCM_SHA256 curveID=29
# 29 = X25519 — Go ≤ 1.22 has no ML-KEM in crypto/tls Go 1.23 negotiates X25519MLKEM768 automatically. Earlier versions cannot, regardless of GODEBUG flags.
Go 1.23 (Aug 2024) added X25519MLKEM768 to the default TLS 1.3 group list as
the highest-priority option. Any HTTP server, gRPC service, database driver, or reverse
proxy built on Go 1.23+ negotiates hybrid PQC automatically with capable peers.
Confirm your runtime
if ! command -v go >/dev/null 2>&1; then
echo 'Go was not found.'
printf 'Install Go 1.23+ now? [y/N] '; read answer
case "$answer" in [Yy]*) echo 'Install Go from https://go.dev/dl/ or your OS package manager, then rerun.' ;; *) exit 1 ;; esac
exit 1
fi
go version
# go version go1.23.x ... Default behavior
You don't need to set tls.Config.CurvePreferences. The defaults already include
X25519MLKEM768 first. If you've explicitly set CurvePreferences,
either remove it or include tls.X25519MLKEM768:
cfg := &tls.Config{
MinVersion: tls.VersionTLS12,
CurvePreferences: []tls.CurveID{
tls.X25519MLKEM768,
tls.X25519,
tls.CurveP256,
},
} GODEBUG knobs
You can disable hybrid PQC for compatibility testing with
GODEBUG=tlsmlkem=0 (default 1 since 1.23). The default flips to
tlsmlkem=1 permanently in 1.24.
Servers
Caddy, Traefik (Go), MinIO, etcd, Vault, Consul, Tailscale's tsnet, NATS, all current Go reverse proxies and HTTP servers — all inherit hybrid PQC for free with a Go 1.23+ build.