{"record":{"id":"55ea8e7a27964bbc","repo":"golang/go","slug":"tls-server-certificate-contains-incorrect-key-typ","errorCode":null,"errorMessage":"tls: server certificate contains incorrect key type for selected ciphersuite","messagePattern":"tls: server certificate contains incorrect key type for selected ciphersuite","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/crypto/tls/key_agreement.go","lineNumber":93,"sourceCode":"\treturn preMasterSecret, nil\n}\n\nfunc (ka rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {\n\treturn errors.New(\"tls: unexpected ServerKeyExchange\")\n}\n\nfunc (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {\n\tpreMasterSecret := make([]byte, 48)\n\tpreMasterSecret[0] = byte(clientHello.vers >> 8)\n\tpreMasterSecret[1] = byte(clientHello.vers)\n\t_, err := io.ReadFull(config.rand(), preMasterSecret[2:])\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\trsaKey, ok := cert.PublicKey.(*rsa.PublicKey)\n\tif !ok {\n\t\treturn nil, nil, errors.New(\"tls: server certificate contains incorrect key type for selected ciphersuite\")\n\t}\n\tencrypted, err := rsa.EncryptPKCS1v15(config.rand(), rsaKey, preMasterSecret)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tckx := new(clientKeyExchangeMsg)\n\tckx.ciphertext = make([]byte, len(encrypted)+2)\n\tckx.ciphertext[0] = byte(len(encrypted) >> 8)\n\tckx.ciphertext[1] = byte(len(encrypted))\n\tcopy(ckx.ciphertext[2:], encrypted)\n\treturn preMasterSecret, ckx, nil\n}\n\n// sha1Hash calculates a SHA1 hash over the given byte slices.\nfunc sha1Hash(slices [][]byte) []byte {\n\thsha1 := sha1.New()\n\tfor _, slice := range slices {\n\t\thsha1.Write(slice)","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/tls/key_agreement.go#L75-L111","documentation":"During TLS 1.0–1.2 RSA key exchange on the client side, the server's certificate public key is not an *rsa.PublicKey. The RSA key agreement requires encrypting the pre-master secret to the server's RSA public key via rsa.EncryptPKCS1v15. If the cert contains an ECDSA, Ed25519, or other non-RSA key, this type assertion fails.","triggerScenarios":"Client calls rsaKeyAgreement.generateClientKeyExchange and attempts cert.PublicKey.(*rsa.PublicKey). The negotiated cipher suite is an RSA key-exchange suite (e.g. TLS_RSA_WITH_AES_128_CBC_SHA), but the server's certificate uses a non-RSA key (e.g. ECDSA P-256).","commonSituations":"Cipher suite and certificate key type mismatch: server presents an ECDSA cert but the client/server negotiated an RSA key exchange cipher suite; misconfigured server that loads the wrong certificate for the negotiated cipher suite; client forces RSA suites while server only has ECDSA certs (or vice versa).","solutions":["Ensure the server certificate key type matches the negotiated cipher suite (RSA cert for RSA suites, ECDSA cert for ECDSA suites).","Configure the client to prefer ECDHE cipher suites that match the server's certificate key type.","Verify the server is loading the correct certificate for the connection.","Use tls.Config.Certificates to provide both RSA and ECDSA certs so the server can select the right one.","Update to TLS 1.3 which decouples key exchange from authentication, avoiding this class of mismatch."],"exampleFix":"// before: server has only ECDSA cert but client negotiates RSA cipher suite\ncfg := &tls.Config{\n    CipherSuites: []uint16{tls.TLS_RSA_WITH_AES_128_CBC_SHA}, // requires RSA cert\n    Certificates: []tls.Certificate{ecdsaCert}, // wrong key type!\n}\n// after: provide matching RSA cert or use ECDHE suites\ncfg := &tls.Config{\n    CipherSuites: []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},\n    Certificates: []tls.Certificate{ecdsaCert}, // now matches\n}","handlingStrategy":"type-guard","validationCode":"// Verify server cert key type before connecting (if cert is known)\nfunc verifyRSACertKeyType(cert *x509.Certificate) error {\n    if _, ok := cert.PublicKey.(*rsa.PublicKey); !ok {\n        return errors.New(\"server certificate is not RSA but RSA key exchange was negotiated\")\n    }\n    return nil\n}","typeGuard":"func isRSAPublicKey(pub any) bool {\n    _, ok := pub.(*rsa.PublicKey)\n    return ok\n}","tryCatchPattern":"// Client-side: handle during handshake\nif err := conn.Handshake(); err != nil {\n    if strings.Contains(err.Error(), \"incorrect key type\") {\n        log.Printf(\"server cert key type mismatch: %v\", err)\n    }\n}","preventionTips":["Prefer ECDHE cipher suites that match the server's cert key type.","Don't force RSA key exchange suites unless you know the server has an RSA cert.","Use TLS 1.3 to avoid cert-key-type/cipher-suite coupling.","Configure client CipherSuites to include both RSA and ECDSA ECDHE variants."],"tags":["tls","tls12","rsa","key-exchange","certificate","cipher-suite","client-side"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:31:55.035Z"}