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

  1. Verify the client TLS library is a recent, well-tested implementation.
  2. If fuzzing, ensure the test harness generates well-formed ClientKeyExchange messages.
  3. Capture the handshake with Wireshark to inspect the ClientKeyExchange structure.
  4. Test with a reference client (openssl s_client) to rule out server-side issues.
  5. 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

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

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/e8f7c8bc94eea2a2. Report an issue: GitHub.