{"record":{"id":"455fca6ef15f2b02","repo":"hashicorp/packer","slug":"ecdsa-verification-failed","errorCode":null,"errorMessage":"ECDSA verification failed","messagePattern":"ECDSA verification failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/attestation/sign_key.go","lineNumber":87,"sourceCode":"\t\tSig:   signature,\n\t}, nil\n}\n\nfunc (s *pemSigner) Verifier(context.Context, BackendConfig) (Verifier, error) {\n\treturn s.verifier, nil\n}\n\nfunc (v *pemVerifier) Verify(_ context.Context, payloadType string, payload, signature []byte) error {\n\tpae := PreAuthEncode(payloadType, payload)\n\n\tswitch publicKey := v.publicKey.(type) {\n\tcase *rsa.PublicKey:\n\t\tdigest := sha256.Sum256(pae)\n\t\treturn rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, digest[:], signature)\n\tcase *ecdsa.PublicKey:\n\t\tdigest := sha256.Sum256(pae)\n\t\tif !ecdsa.VerifyASN1(publicKey, digest[:], signature) {\n\t\t\treturn fmt.Errorf(\"ECDSA verification failed\")\n\t\t}\n\t\treturn nil\n\tcase ed25519.PublicKey:\n\t\tif !ed25519.Verify(publicKey, pae, signature) {\n\t\t\treturn fmt.Errorf(\"Ed25519 verification failed\")\n\t\t}\n\t\treturn nil\n\tdefault:\n\t\treturn fmt.Errorf(\"unsupported public key type %T\", v.publicKey)\n\t}\n}\n\nfunc (v *pemVerifier) KeyID() string {\n\treturn v.keyID\n}\n\nfunc LoadPEMVerifier(path string) (Verifier, error) {\n\tcontents, err := os.ReadFile(path)","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/hashicorp/packer/blob/eb36e3c3e48a036f3e8cc94087636ee72e1303c9/internal/attestation/sign_key.go#L69-L105","documentation":"pemVerifier.Verify verifies an attestation signature using the loaded public key. For *ecdsa.PublicKey keys it hashes the pre-auth-encoded payload with SHA-256 and calls ecdsa.VerifyASN1; when that returns false the verifier returns the literal error \"ECDSA verification failed\". This is a signature-validity failure: the signature bytes do not cryptographically match the payload under this ECDSA public key.","triggerScenarios":"Calling pemVerifier.Verify(ctx, payloadType, payload, signature) where the verifier's publicKey is *ecdsa.PublicKey and ecdsa.VerifyASN1(publicKey, sha256(PreAuthEncode(payloadType,payload)), signature) returns false — wrong key, tampered payload, truncated/mangled signature, or a signature produced with a different payload encoding.","commonSituations":"Verifying with the wrong public key (signature was made by a different signer, e.g. rotated keys); the payload bytes differ between signing and verification (whitespace, re-serialization, changed payloadType string); signature was base64/hex mangled in transit; verifying an RSA or Ed25519 signature against an ECDSA verifier.","solutions":["Confirm the verifier's PEM public key matches the private key that produced the signature — compare the KeyID (SHA-256 hex of the PEM public key) from the Signature against the verifier's KeyID().","Ensure the exact same payloadType string and payload bytes are passed to Verify as were passed to Sign; PreAuthEncode makes the signature sensitive to both.","Check the signature encoding: decode it (e.g. base64/hex) exactly as produced and do not truncate or re-encode the ASN.1 DER signature bytes.","If signatures were produced by an external tool, confirm it uses the same scheme: ECDSA over SHA-256 of the PAE, ASN.1-encoded (not P1363 fixed-size r||s) — convert if necessary."],"exampleFix":"// before: verifying with an unrelated public key\nverifier, _ := attestation.LoadPEMVerifier(\"other-key.pub\")\nerr := verifier.Verify(ctx, payloadType, payload, sig.Sig) // ECDSA verification failed\n\n// after: key-match check first (sign_key.go exposes KeyID as sha256 hex of the public PEM)\nverifier, _ := attestation.LoadPEMVerifier(\"signer-key.pub\")\nif verifier.KeyID() != sig.KeyID {\n\treturn fmt.Errorf(\"signature key %s does not match verifier %s\", sig.KeyID, verifier.KeyID())\n}\nerr := verifier.Verify(ctx, payloadType, payload, sig.Sig)","handlingStrategy":"validation","validationCode":"// Verify key correspondence before calling Verify\nif verifier.KeyID() != sig.KeyID {\n\treturn fmt.Errorf(\"signature made with key %s but verifier is %s\", sig.KeyID, verifier.KeyID())\n}\n// Confirm ECDSA verifier type\nswitch v := verifier.(type) {\ncase *attestation.PEMVerifier:\n\t// expected; proceed\n}","typeGuard":"func isECDSAVerifier(v attestation.Verifier, pub crypto.PublicKey) bool {\n\t_, ok := pub.(*ecdsa.PublicKey)\n\treturn ok\n}","tryCatchPattern":"if err := verifier.Verify(ctx, payloadType, payload, sig.Sig); err != nil {\n\tif err.Error() == \"ECDSA verification failed\" {\n\t\t// signature/payload/key mismatch — do not retry blindly;\n\t\t// compare sig.KeyID vs verifier.KeyID() and re-check payload bytes\n\t}\n\treturn fmt.Errorf(\"attestation verify: %w\", err)\n}","preventionTips":["Always pair signatures with their KeyID and check it matches the verifier before cryptographic verification.","Transport signatures and payloads in byte-exact encodings (base64 std encoding) and never re-serialize payloads between sign and verify.","Derive the Verifier from the same Signer (signer.Verifier) instead of loading an independent public key file.","Pin and version the payloadType strings so signers and verifiers agree on the PAE input."],"tags":["attestation","signature-verification","ecdsa","crypto"],"backgroundTag":"signature-verification-failed","analyzedSha":"eb36e3c3e48a036f3e8cc94087636ee72e1303c9","analyzedAt":"2026-09-05T13:20:43.127Z","contentChangedAt":"2026-09-05T13:20:43.127Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}