golang/go · error
tls: invalid ClientKeyExchange message
Error message
tls: invalid ClientKeyExchange message
What it means
A sentinel error (errClientKeyExchange) used in TLS 1.0–1.2 RSA and ECDHE key exchange when the ClientKeyExchange message from the client is malformed. For RSA: the ciphertext length field doesn't match the actual ciphertext, or the ciphertext is too short (< 2 bytes). For ECDHE: the public key length field doesn't match, the peer public key is invalid, or ECDH computation fails. The error is deliberately generic to avoid leaking information about which validation failed.
Source
Thrown at src/crypto/tls/key_agreement.go:39
// agreement protocol by generating and processing key exchange messages.
type keyAgreement interface {
// On the server side, the first two methods are called in order.
// In the case that the key agreement protocol doesn't use a
// ServerKeyExchange message, generateServerKeyExchange can return nil,
// nil.
generateServerKeyExchange(*Config, *Certificate, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, error)
processClientKeyExchange(*Config, *Certificate, *clientKeyExchangeMsg, uint16) ([]byte, error)
// On the client side, the next two methods are called in order.
// This method may not be called if the server doesn't send a
// ServerKeyExchange message.
processServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg, *x509.Certificate, *serverKeyExchangeMsg) error
generateClientKeyExchange(*Config, *clientHelloMsg, *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error)
}
var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message")
var errServerKeyExchange = errors.New("tls: invalid ServerKeyExchange message")
// rsaKeyAgreement implements the standard TLS key agreement where the client
// encrypts the pre-master secret to the server's public key.
type rsaKeyAgreement struct{}
func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
return nil, nil
}
func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
if len(ckx.ciphertext) < 2 {
return nil, errClientKeyExchange
}
ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])
if ciphertextLen != len(ckx.ciphertext)-2 {
return nil, errClientKeyExchange
}View on GitHub (pinned to b6b368adc5)
Solutions
- Verify the client TLS library is a recent, well-tested implementation.
- If fuzzing, ensure the test harness generates well-formed ClientKeyExchange messages.
- Capture the handshake with Wireshark to inspect the ClientKeyExchange structure.
- Test with a reference client (openssl s_client) to rule out server-side issues.
- If the error is intermittent, check for network-level corruption or MTU/MSS issues.
Defensive patterns
Strategy: try-catch
Validate before calling
// This is a server-side protocol validation; callers cannot pre-check.
// For testing, validate your ClientKeyExchange encoding:
func validateRSAClientKeyExchange(ckx *clientKeyExchangeMsg) error {
if len(ckx.ciphertext) < 2 {
return errors.New("ciphertext too short")
}
declaredLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])
if declaredLen != len(ckx.ciphertext)-2 {
return errors.New("ciphertext length mismatch")
}
return nil
} Try / catch
// Server-side: these are protocol-level errors from malicious/buggy clients
if err := conn.Handshake(); err != nil {
if errors.Is(err, errClientKeyExchange) {
log.Printf("malformed ClientKeyExchange from %v", conn.RemoteAddr())
}
conn.Close()
} Prevention
- Use well-tested client TLS libraries.
- Monitor for malformed handshake messages as potential attack indicators.
- Ensure network infrastructure doesn't corrupt TLS records.
- Run interop tests against multiple client implementations.
When it happens
Trigger: Server processes a clientKeyExchangeMsg during TLS 1.0-1.2 handshake. For RSA key agreement: ckx.ciphertext is < 2 bytes, or the 2-byte length prefix doesn't match len(ciphertext)-2. For ECDHE: the client's ECDHE public key is empty, the length byte doesn't match, the key isn't on the right curve, or ECDH fails.
Common situations: Malformed or truncated ClientKeyExchange from a buggy client; a network issue corrupting the message; a fuzzing tool generating invalid handshake messages; a client library bug in encoding the key exchange payload; an attacker probing the server with crafted messages.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- tls: certificate private key does not implement crypto.Decry
- tls: no supported elliptic curves offered
- tls: invalid outer extensions
- tls: invalid reconstructed inner client hello
- tls: malformed encrypted_client_hello extension
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/e8f7c8bc94eea2a2.
Report an issue: GitHub.