Here's something that's been sitting in the back of my mind since I read Filippo Valsorda's deep dive on the origins of ECDSA curve seeds.
The thing nobody checks
You're running a TLS stack. Maybe it's nginx, maybe it's Caddy, maybe it's a Go service. You've got ECDSA certificates because they're smaller and faster than RSA. P-256, P-384, maybe P-521 if you're feeling fancy.
You probably know the curve parameters. You might even know the generator point. But do you know where the seed came from?
The NIST curves (P-256, P-384, P-521) use seeds that were supposedly generated by SHA-1 hashing some unexplained input. The seeds are:
P-256: c49d3608 86e70493 6a6678e1 139d26b7 819f7e90
P-384: a335926a a319a27a 1d00896a 6773a482 7acdac73
P-521: d09e8800 291cb853 96cc6717 393284aa a0da64ba
Nobody knows what was hashed to produce these. The NSA generated them in the 90s. The explanation was "we hashed a random value" but the input was never published.
Why this matters for ops
If you're running a modern TLS stack, you're likely using one of these curves. The practical implication isn't that they're backdoored — the cryptographic community has analyzed them extensively and found no weakness. The implication is trust.
When you configure ssl_ecdh_curve secp256r1 in nginx or let Go's crypto/tls pick P-256 by default, you're trusting a seed with unknown provenance. For most of us, that's fine. The curves work. The math checks out.
But if you're in a regulated environment, or you're building something where "trust me, the NSA said it's random" doesn't pass audit, you have options:
1. Use Curve25519 / Ed25519
These use a transparent seed: the integer 9 for Curve25519, and a hash of "Ed25519" for Ed25519. No mystery. Widely supported in modern TLS libraries.
# nginx
ssl_ecdh_curve X25519:secp256r1;
// Go
tls.Config{
CurvePreferences: []tls.CurveID{tls.X25519, tls.CurveP256},
}
2. Use brainpool curves if you need NIST compliance but want transparent seeds
Brainpool curves (brainpoolP256r1, etc.) use seeds derived from pi and e. Completely transparent. Less widely supported though.
3. Just know what you're running
Run this and see what your stack actually negotiates:
openssl s_client -connect yourhost:443 -curves P-256:X25519 </dev/null 2>/dev/null | grep "Curve is"
The actual takeaway
You don't need to rip out P-256 tomorrow. But you should know which curves your infrastructure actually uses, and why. If your compliance requirements demand transparent cryptographic parameters, Curve25519 is sitting right there, supported by every modern TLS implementation.
The seeds aren't a vulnerability. They're a trust decision. Make it consciously.
Schiff Heimlich | Sysadmin who reads the RFCs so you don't have to
Top comments (0)