hashicorp/packer · error
ECDSA verification failed
Error message
ECDSA verification failed
What it means
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.
Source
Thrown at internal/attestation/sign_key.go:87
Sig: signature,
}, nil
}
func (s *pemSigner) Verifier(context.Context, BackendConfig) (Verifier, error) {
return s.verifier, nil
}
func (v *pemVerifier) Verify(_ context.Context, payloadType string, payload, signature []byte) error {
pae := PreAuthEncode(payloadType, payload)
switch publicKey := v.publicKey.(type) {
case *rsa.PublicKey:
digest := sha256.Sum256(pae)
return rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, digest[:], signature)
case *ecdsa.PublicKey:
digest := sha256.Sum256(pae)
if !ecdsa.VerifyASN1(publicKey, digest[:], signature) {
return fmt.Errorf("ECDSA verification failed")
}
return nil
case ed25519.PublicKey:
if !ed25519.Verify(publicKey, pae, signature) {
return fmt.Errorf("Ed25519 verification failed")
}
return nil
default:
return fmt.Errorf("unsupported public key type %T", v.publicKey)
}
}
func (v *pemVerifier) KeyID() string {
return v.keyID
}
func LoadPEMVerifier(path string) (Verifier, error) {
contents, err := os.ReadFile(path)View on GitHub (pinned to eb36e3c3e4)
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.
Example fix
// before: verifying with an unrelated public key
verifier, _ := attestation.LoadPEMVerifier("other-key.pub")
err := verifier.Verify(ctx, payloadType, payload, sig.Sig) // ECDSA verification failed
// after: key-match check first (sign_key.go exposes KeyID as sha256 hex of the public PEM)
verifier, _ := attestation.LoadPEMVerifier("signer-key.pub")
if verifier.KeyID() != sig.KeyID {
return fmt.Errorf("signature key %s does not match verifier %s", sig.KeyID, verifier.KeyID())
}
err := verifier.Verify(ctx, payloadType, payload, sig.Sig) Defensive patterns
Strategy: validation
Validate before calling
// Verify key correspondence before calling Verify
if verifier.KeyID() != sig.KeyID {
return fmt.Errorf("signature made with key %s but verifier is %s", sig.KeyID, verifier.KeyID())
}
// Confirm ECDSA verifier type
switch v := verifier.(type) {
case *attestation.PEMVerifier:
// expected; proceed
} Type guard
func isECDSAVerifier(v attestation.Verifier, pub crypto.PublicKey) bool {
_, ok := pub.(*ecdsa.PublicKey)
return ok
} Try / catch
if err := verifier.Verify(ctx, payloadType, payload, sig.Sig); err != nil {
if err.Error() == "ECDSA verification failed" {
// signature/payload/key mismatch — do not retry blindly;
// compare sig.KeyID vs verifier.KeyID() and re-check payload bytes
}
return fmt.Errorf("attestation verify: %w", err)
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Ed25519 verification failed
- sign payload: %w
- private key does not implement crypto.Signer
- signature verification failed
- signing_mode %q does not support Sigstore bundle emission
AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05).
Data as JSON: /api/errors/455fca6ef15f2b02.
Report an issue: GitHub.