{"record":{"id":"e903bcd3b35272b6","repo":"golang/go","slug":"ecdsa-verification-failure","errorCode":null,"errorMessage":"ECDSA verification failure","messagePattern":"ECDSA verification failure","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/tls/auth.go","lineNumber":39,"sourceCode":"\n// verifyHandshakeSignature verifies a signature against unhashed handshake contents.\nfunc verifyHandshakeSignature(sigType uint8, pubkey crypto.PublicKey, hashFunc crypto.Hash, signed, sig []byte) error {\n\tif hashFunc != directSigning {\n\t\tif !hashFunc.Available() {\n\t\t\treturn fmt.Errorf(\"hash function unavailable: %v\", hashFunc)\n\t\t}\n\t\th := hashFunc.New()\n\t\th.Write(signed)\n\t\tsigned = h.Sum(nil)\n\t}\n\tswitch sigType {\n\tcase signatureECDSA:\n\t\tpubKey, ok := pubkey.(*ecdsa.PublicKey)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"expected an ECDSA public key, got %T\", pubkey)\n\t\t}\n\t\tif !ecdsa.VerifyASN1(pubKey, signed, sig) {\n\t\t\treturn errors.New(\"ECDSA verification failure\")\n\t\t}\n\tcase signatureEd25519:\n\t\tpubKey, ok := pubkey.(ed25519.PublicKey)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"expected an Ed25519 public key, got %T\", pubkey)\n\t\t}\n\t\tif !ed25519.Verify(pubKey, signed, sig) {\n\t\t\treturn errors.New(\"Ed25519 verification failure\")\n\t\t}\n\tcase signatureMLDSA:\n\t\tpubKey, ok := pubkey.(*mldsa.PublicKey)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"expected an ML-DSA public key, got %T\", pubkey)\n\t\t}\n\t\tif err := mldsa.Verify(pubKey, signed, sig, nil); err != nil {\n\t\t\treturn fmt.Errorf(\"ML-DSA verification failure: %w\", err)\n\t\t}\n\tcase signaturePKCS1v15:","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/tls/auth.go#L21-L57","documentation":"Thrown by tls verifyHandshakeSignature when ecdsa.VerifyASN1 returns false for an ECDSA signature over the handshake transcript. The public key type matched (it is *ecdsa.PublicKey), but the signature is mathematically invalid for the given signed data. This is a TLS-level signature check on the peer's signed handshake message.","triggerScenarios":"During a TLS handshake, the peer signs handshake data with ECDSA and the local side's ecdsa.VerifyASN1(pub, signed, sig) returns false. Reached via signatureECDSA in verifyHandshakeSignature, used by TLS 1.2 and 1.3.","commonSituations":"Mismatched curve between cert and signature; corrupted signature over the wire; wrong transcript bytes due to a MITM or buggy peer; key reuse across contexts; ASN.1 encoding produced by a non-conformant signer.","solutions":["Verify the server certificate is valid and unmodified (full chain, correct curve).","Capture the handshake with a TLS tracer to confirm the signed bytes and signature match what the peer sent.","Ensure client and server agree on signature algorithm (curve + hash) per the signature_algorithms extension.","If writing the signer, confirm ecdsa.SignASN1 and VerifyASN1 use the same digest and curve."],"exampleFix":"// before (buggy signer hashes twice)\nsig, _ := ecdsa.SignASN1(rand, priv, alreadyHashed)\n// peer verifies over the raw transcript -> mismatch\n\n// after\nsig, err := ecdsa.SignASN1(rand, priv, transcript)\nif err != nil { return err }\n// verifier hashes per the negotiated hash; pass the right input","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"func isECDSAPubKey(k any) bool {\n    _, ok := k.(*ecdsa.PublicKey)\n    return ok\n}","tryCatchPattern":"// During TLS verification, surface ECDSA failures distinctly.\nif _, err := tls.Dial(\"tcp\", addr, cfg); err != nil {\n    var verErr *tls.RecordHeaderError\n    if strings.Contains(err.Error(), \"ECDSA verification failure\") {\n        log.Printf(\"ECDSA handshake failed (cert/sig/curve mismatch): %v\", err)\n    }\n    return err\n}","preventionTips":["Ensure signer and verifier use the same curve and hash.","Verify the full certificate chain before trusting an ECDSA signature.","Log signature failures with the negotiated curve/hash to diagnose mismatches.","Test signing/verifying round-trips with crypto/ecdsa directly before TLS integration."],"tags":["crypto","tls","ecdsa","signature","go"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}