{"record":{"id":"e8f7c8bc94eea2a2","repo":"golang/go","slug":"tls-invalid-clientkeyexchange-message","errorCode":null,"errorMessage":"tls: invalid ClientKeyExchange message","messagePattern":"tls: invalid ClientKeyExchange message","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/tls/key_agreement.go","lineNumber":39,"sourceCode":"// agreement protocol by generating and processing key exchange messages.\ntype keyAgreement interface {\n\t// On the server side, the first two methods are called in order.\n\n\t// In the case that the key agreement protocol doesn't use a\n\t// ServerKeyExchange message, generateServerKeyExchange can return nil,\n\t// nil.\n\tgenerateServerKeyExchange(*Config, *Certificate, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, error)\n\tprocessClientKeyExchange(*Config, *Certificate, *clientKeyExchangeMsg, uint16) ([]byte, error)\n\n\t// On the client side, the next two methods are called in order.\n\n\t// This method may not be called if the server doesn't send a\n\t// ServerKeyExchange message.\n\tprocessServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg, *x509.Certificate, *serverKeyExchangeMsg) error\n\tgenerateClientKeyExchange(*Config, *clientHelloMsg, *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error)\n}\n\nvar errClientKeyExchange = errors.New(\"tls: invalid ClientKeyExchange message\")\nvar errServerKeyExchange = errors.New(\"tls: invalid ServerKeyExchange message\")\n\n// rsaKeyAgreement implements the standard TLS key agreement where the client\n// encrypts the pre-master secret to the server's public key.\ntype rsaKeyAgreement struct{}\n\nfunc (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {\n\treturn nil, nil\n}\n\nfunc (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {\n\tif len(ckx.ciphertext) < 2 {\n\t\treturn nil, errClientKeyExchange\n\t}\n\tciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])\n\tif ciphertextLen != len(ckx.ciphertext)-2 {\n\t\treturn nil, errClientKeyExchange\n\t}","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/tls/key_agreement.go#L21-L57","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// This is a server-side protocol validation; callers cannot pre-check.\n// For testing, validate your ClientKeyExchange encoding:\nfunc validateRSAClientKeyExchange(ckx *clientKeyExchangeMsg) error {\n    if len(ckx.ciphertext) < 2 {\n        return errors.New(\"ciphertext too short\")\n    }\n    declaredLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])\n    if declaredLen != len(ckx.ciphertext)-2 {\n        return errors.New(\"ciphertext length mismatch\")\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"// Server-side: these are protocol-level errors from malicious/buggy clients\nif err := conn.Handshake(); err != nil {\n    if errors.Is(err, errClientKeyExchange) {\n        log.Printf(\"malformed ClientKeyExchange from %v\", conn.RemoteAddr())\n    }\n    conn.Close()\n}","preventionTips":["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."],"tags":["tls","tls12","handshake","key-exchange","client-key-exchange","server-side"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}