hashicorp/packer · error
Ed25519 verification failed
Error message
Ed25519 verification failed
What it means
pemVerifier.Verify handles ed25519.PublicKey verifiers by calling ed25519.Verify with the raw pre-auth-encoded payload (Ed25519 signs the message directly, no pre-hashing). When ed25519.Verify returns false, the verifier returns the literal error "Ed25519 verification failed". Like the ECDSA case, this indicates the signature does not cryptographically match the payload under this Ed25519 public key.
Source
Thrown at internal/attestation/sign_key.go:92
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)
if err != nil {
return nil, fmt.Errorf("read verifier %q: %w", path, err)
}
publicKey, rawVerifier, err := loadPEMPublicKey(contents)View on GitHub (pinned to eb36e3c3e4)
Solutions
- Verify the Ed25519 public key PEM corresponds to the signing key — compare Signature.KeyID with verifier.KeyID() before attempting verification.
- Pass the identical payloadType and payload bytes used at signing time; Ed25519 here verifies the raw PAE bytes, so any difference fails.
- Ensure the signature is exactly 64 bytes of raw Ed25519 signature data and was not base64-decoded incorrectly or truncated.
- If signatures come from an external Ed25519 library, confirm it signs the same message bytes (the PAE), not a pre-hash or a different canonicalization.
Example fix
// before: mismatched algorithm pair
rsaSigner, _ := attestation.NewSigner(ctx, cfgWithRSAKey) // RSA key
edVerifier, _ := attestation.LoadPEMVerifier("ed25519-pub.pem")
err := edVerifier.Verify(ctx, payloadType, payload, sig.Sig) // Ed25519 verification failed
// after: derive the verifier from the signer so algorithms always match
verifier, _ := signer.Verifier(ctx, cfg)
err := verifier.Verify(ctx, payloadType, payload, sig.Sig) Defensive patterns
Strategy: validation
Validate before calling
if verifier.KeyID() != sig.KeyID {
return fmt.Errorf("signature made with key %s but verifier is %s", sig.KeyID, verifier.KeyID())
}
if len(sig.Sig) != ed25519.SignatureSize {
return fmt.Errorf("bad ed25519 signature length %d, want %d", len(sig.Sig), ed25519.SignatureSize)
} Type guard
func isEd25519Verifier(pub crypto.PublicKey) bool {
_, ok := pub.(ed25519.PublicKey)
return ok
} Try / catch
if err := verifier.Verify(ctx, payloadType, payload, sig.Sig); err != nil {
if err.Error() == "Ed25519 verification failed" {
// mismatch: check key pairing and that payload bytes are identical to signing input
}
return fmt.Errorf("attestation verify: %w", err)
} Prevention
- Use signer.Verifier(ctx, cfg) to obtain the matching verifier rather than a separately loaded PEM.
- Validate that the signature is exactly 64 bytes before verification for Ed25519 keys.
- Never mix key algorithms across rotate operations: keep old verifiers available for old signatures.
- Keep payloadType and payload byte-identical between sign and verify; PreAuthEncode makes any difference fatal.
When it happens
Trigger: Calling pemVerifier.Verify(ctx, payloadType, payload, signature) where the verifier's publicKey is ed25519.PublicKey and ed25519.Verify(publicKey, PreAuthEncode(payloadType,payload), signature) returns false — wrong key, altered payload, corrupted or wrongly encoded signature.
Common situations: Using an Ed25519 public key to verify a signature made by an RSA/ECDSA signer (or vice versa); passing the un-hashed or differently-encoded payload to Verify while the signer hashed it externally; signature bytes damaged by text-mode transport or bad base64 handling; key rotation leaving old signatures verified against new keys.
Related errors
- ECDSA 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/a78adb15c291c7d5.
Report an issue: GitHub.