golang/go · error

ed25519: invalid signature

Error message

ed25519: invalid signature

What it means

Returned by verifyWithDom when sig[63] & 224 != 0 — i.e. the high three bits of the 32-byte S scalar are non-zero. Ed25519 mandates S be canonical (less than the group order L, ~2^252), so the high bits must be zero. A signature failing this check is malformed or crafted to exploit non-canonical scalars.

Source

Thrown at src/crypto/internal/fips140/ed25519/ed25519.go:296

}

func VerifyCtx(pub *PublicKey, message []byte, sig []byte, context string) error {
	fipsSelfTest()
	// FIPS 186-5 specifies Ed25519 and Ed25519ph (with context), but not Ed25519ctx.
	fips140.RecordNonApproved()
	if l := len(context); l > 255 {
		return errors.New("ed25519: bad Ed25519ctx context length: " + strconv.Itoa(l))
	}
	return verifyWithDom(pub, message, sig, domPrefixCtx, context)
}

func verifyWithDom(pub *PublicKey, message, sig []byte, domPrefix, context string) error {
	if l := len(sig); l != signatureSize {
		return errors.New("ed25519: bad signature length: " + strconv.Itoa(l))
	}

	if sig[63]&224 != 0 {
		return errors.New("ed25519: invalid signature")
	}

	kh := sha512.New()
	if domPrefix != domPrefixPure {
		kh.Write([]byte(domPrefix))
		kh.Write([]byte{byte(len(context))})
		kh.Write([]byte(context))
	}
	kh.Write(sig[:32])
	kh.Write(pub.aBytes[:])
	kh.Write(message)
	hramDigest := make([]byte, 0, sha512Size)
	hramDigest = kh.Sum(hramDigest)
	k, err := edwards25519.NewScalar().SetUniformBytes(hramDigest)
	if err != nil {
		panic("ed25519: internal error: setting scalar failed")
	}

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Reject the signature as malformed — do not attempt to 'normalize' it.
  2. Audit the signer if many signatures fail this check; it likely is not producing canonical S.
  3. Verify against a reference implementation (e.g. the standard ed25519 package) to confirm the bytes are genuinely malformed.
Defensive patterns

Strategy: try-catch

Validate before calling

// Cheap pre-check: high 3 bits of S must be zero (S < 2^252 is enforced more strictly next).
if len(sig) == 64 && sig[63]&224 != 0 {
    return ErrMalformedSignature
}
return ed25519.Verify(pub, message, sig)

Try / catch

if err := ed25519.Verify(pub, message, sig); err != nil {
    if strings.Contains(err.Error(), "invalid signature") {
        // covers high-bits-set, non-canonical S, and equation failure
        return ErrSignatureRejected
    }
    return err
}

Prevention

When it happens

Trigger: Calling an Ed25519 Verify variant with a 64-byte signature whose trailing 32 bytes encode an S value >= L (high bits set).

Common situations: Corrupted signature bytes; signature from a buggy signer that did not reduce S mod L; adversarial input probing for verification malleability; byte-swap or endianness mistake.

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/06c438f35ef2ab0d. Report an issue: GitHub.