{"record":{"id":"ee3e480abc606bcf","repo":"golang/go","slug":"tls-server-s-identity-changed-during-renegotiatio","errorCode":null,"errorMessage":"tls: server's identity changed during renegotiation","messagePattern":"tls: server's identity changed during renegotiation","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/tls/handshake_client.go","lineNumber":696,"sourceCode":"\t\t}\n\t}\n\n\tif c.handshakes == 0 {\n\t\t// If this is the first handshake on a connection, process and\n\t\t// (optionally) verify the server's certificates.\n\t\tif err := c.verifyServerCertificate(certMsg.certificates); err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\t// This is a renegotiation handshake. We require that the\n\t\t// server's identity (i.e. leaf certificate) is unchanged and\n\t\t// thus any previous trust decision is still valid.\n\t\t//\n\t\t// See https://mitls.org/pages/attacks/3SHAKE for the\n\t\t// motivation behind this requirement.\n\t\tif !bytes.Equal(c.peerCertificates[0].Raw, certMsg.certificates[0]) {\n\t\t\tc.sendAlert(alertBadCertificate)\n\t\t\treturn errors.New(\"tls: server's identity changed during renegotiation\")\n\t\t}\n\t}\n\n\tkeyAgreement := hs.suite.ka(c.vers)\n\n\tskx, ok := msg.(*serverKeyExchangeMsg)\n\tif ok {\n\t\terr = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, c.peerCertificates[0], skx)\n\t\tif err != nil {\n\t\t\tc.sendAlert(alertIllegalParameter)\n\t\t\treturn err\n\t\t}\n\t\tif keyAgreement, ok := keyAgreement.(*ecdheKeyAgreement); ok {\n\t\t\tc.curveID = keyAgreement.curveID\n\t\t\tc.peerSigAlg = keyAgreement.signatureAlgorithm\n\t\t}\n\n\t\tmsg, err = c.readHandshake(&hs.finishedHash)","sourceCodeStart":678,"sourceCodeEnd":714,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/tls/handshake_client.go#L678-L714","documentation":"During TLS renegotiation (TLS 1.2 and earlier; TLS 1.3 has none), Go requires the server's leaf certificate to be byte-identical (c.peerCertificates[0].Raw) to the one from the original handshake. This defeats 3SHAKE-style synchronization attacks (see mitls.org/pages/attacks/3SHAKE in the source comment). A different leaf on renegotiation is treated as an attack or a serious server-side inconsistency.","triggerScenarios":"Server rotated its certificate between the original handshake and a renegotiation; server pool behind a load balancer serving different leaf certs per node; renegotiation triggered by IIS demanding a client certificate mid-connection.","commonSituations":"Long-lived connections spanning a certificate renewal window; clusters with non-uniform certificates; Windows IIS renegotiation-for-client-cert flows.","solutions":["Prefer TLS 1.3 (no renegotiation) by setting MinVersion = VersionTLS13.","Ensure every node in the server pool serves the identical leaf certificate.","Coordinate certificate rotation so it does not span active renegotiating connections.","Reduce connection lifetime below the rotation interval."],"exampleFix":"// before: allows renegotiation on long-lived TLS 1.2 conn\ncfg := &tls.Config{Renegotiation: tls.RenegotiateFreelyAsClient}\n// after: move to TLS 1.3 where renegotiation does not exist\ncfg := &tls.Config{MinVersion: tls.VersionTLS13}","handlingStrategy":"validation","validationCode":"// Avoid renegotiation entirely by requiring TLS 1.3.\nfunc avoidRenegotiation(cfg *tls.Config) {\n    cfg.MinVersion = tls.VersionTLS13\n}","typeGuard":"func isIdentityChangedRenegotiation(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"server's identity changed during renegotiation\")\n}","tryCatchPattern":"if _, err := tls.Dial(\"tcp\", addr, cfg); err != nil {\n    if isIdentityChangedRenegotiation(err) {\n        // The server cluster is serving inconsistent certs; cannot safely retry.\n        reportClusterInconsistency(addr, err)\n    }\n}","preventionTips":["Set MinVersion = VersionTLS13 to eliminate renegotiation.","Keep server-pool leaf certificates uniform.","Coordinate cert rotation outside active long-lived connections."],"tags":["tls","renegotiation","certificates","security"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}