golang/go · critical
tls: failed to sign ECDHE parameters: %s
Error message
tls: failed to sign ECDHE parameters: %s
What it means
During TLS 1.0–1.2 ECDHE ServerKeyExchange parameter signing (modern path using crypto.SignMessage), the private key's Sign operation failed. The underlying error is appended via %s. This is a server-side signing failure, not a protocol error — the key could not produce a signature over the ECDHE parameters (client random + server random + server ECDHE params).
Source
Thrown at src/crypto/tls/key_agreement.go:217
sigType, sigHash, err := typeAndHashFromSignatureScheme(ka.signatureAlgorithm)
if err != nil {
return nil, err
}
if sigHash == crypto.SHA1 {
tlssha1.Value() // ensure godebug is initialized
tlssha1.IncNonDefault()
}
signed := slices.Concat(clientHello.random, hello.random, serverECDHEParams)
if (sigType == signaturePKCS1v15 || sigType == signatureRSAPSS) != ka.isRSA {
return nil, errors.New("tls: certificate cannot be used with the selected cipher suite")
}
signOpts := crypto.SignerOpts(sigHash)
if sigType == signatureRSAPSS {
signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: sigHash}
}
sig, err = crypto.SignMessage(priv, config.rand(), signed, signOpts)
if err != nil {
return nil, errors.New("tls: failed to sign ECDHE parameters: " + err.Error())
}
} else {
sigType, sigHash, err := legacyTypeAndHashFromPublicKey(priv.Public())
if err != nil {
return nil, err
}
signed := hashForServerKeyExchange(sigType, clientHello.random, hello.random, serverECDHEParams)
if (sigType == signaturePKCS1v15) != ka.isRSA {
return nil, errors.New("tls: certificate cannot be used with the selected cipher suite")
}
sig, err = priv.Sign(config.rand(), signed, sigHash)
if err != nil {
return nil, errors.New("tls: failed to sign ECDHE parameters: " + err.Error())
}
}
skx := new(serverKeyExchangeMsg)
sigAndHashLen := 0View on GitHub (pinned to b6b368adc5)
Solutions
- Verify the private key file is valid: openssl rsa -check (RSA) or openssl ec -check (ECDSA).
- If using an HSM/PKCS#11: ensure the token is connected, unlocked, and the session is active.
- Test the key independently: write a small program that calls priv.Sign() outside of TLS.
- If using a custom crypto.Signer, debug its Sign method implementation.
- Ensure the key type matches the signing algorithm (RSA-PSS requires RSA key, ECDSA requires EC key).
Example fix
// Debug the signing key in isolation
// before: untested custom signer in production
cert := tls.Certificate{PrivateKey: customKey}
// after: verify Sign works outside TLS first
sig, err := customKey.Sign(rand.Reader, testHash, nil)
if err != nil {
log.Fatal("key signing failed:", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
// Verify the key can sign before starting the server
func testSigning(key crypto.Signer) error {
digest := make([]byte, 32)
opts := crypto.Hash(0) // vary based on key type
switch key.Public().(type) {
case *rsa.PublicKey:
opts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: crypto.SHA256}
}
_, err := key.Sign(rand.Reader, digest, opts)
return err
} Try / catch
// Verify signing capability at startup
if err := testSigning(cert.PrivateKey.(crypto.Signer)); err != nil {
log.Fatal("key cannot sign ECDHE parameters: ", err)
}
// Runtime:
if err := conn.Handshake(); err != nil {
if strings.Contains(err.Error(), "failed to sign ECDHE parameters") {
log.Printf("ECDHE signing failure: %v", err)
}
} Prevention
- Test key signing at startup before accepting connections.
- For HSM-backed keys, verify the signing path and session management.
- Use standard key types loaded via tls.LoadX509KeyPair.
- Monitor HSM health and connection stability.
When it happens
Trigger: Server calls crypto.SignMessage(priv, config.rand(), signed, signOpts) and it returns an error. Causes: HSM/PKCS#11 failure, corrupted key, unsupported sign options, RSA-PSS with wrong salt length, key revoked or locked.
Common situations: HSM or PKCS#11 token disconnected or session expired; corrupted key file; RSA key that doesn't support PSS; key in a hardware module requiring authentication that wasn't provided; a custom crypto.Signer implementation with a bug in its Sign method.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- tls: certificate cannot be used with the selected cipher sui
- tls: failed to sign handshake: %s
- tls: certificate private key does not implement crypto.Decry
- tls: no supported elliptic curves offered
- tls: internal error: supportsCurve accepted unimplemented cu
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/81d3d695ec399971.
Report an issue: GitHub.