golang/go · error
ed25519: bad signature length: {l}
Error message
ed25519: bad signature length: {l} What it means
Returned by verifyWithDom when the signature slice is not exactly signatureSize (64) bytes — a 32-byte R followed by a 32-byte S, per RFC 8032. Apply to Sign/SignPH/SignCtx verification paths and to pure Verify.
Source
Thrown at src/crypto/internal/fips140/ed25519/ed25519.go:292
if l := len(context); l > 255 {
return errors.New("ed25519: bad Ed25519ph context length: " + strconv.Itoa(l))
}
return verifyWithDom(pub, message, sig, domPrefixPh, context)
}
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)View on GitHub (pinned to b6b368adc5)
Solutions
- Pass exactly 64 raw bytes for the signature.
- Decode hex/base64 first and assert length==64.
- If you received a DER signature, you are on the wrong algorithm — Ed25519 uses raw concatenation, not DER.
Example fix
// before
ok := ed25519.Verify(pub, msg, []byte(sigHex))
// after
b, err := hex.DecodeString(sigHex)
if err != nil { return err }
if len(b) != 64 { return fmt.Errorf("ed25519 sig must be 64 bytes") }
err = ed25519.Verify(pub, msg, b) Defensive patterns
Strategy: validation
Validate before calling
const ed25519SigSize = 64
if len(sig) != ed25519SigSize {
return fmt.Errorf("ed25519 signature must be %d bytes, got %d", ed25519SigSize, len(sig))
}
return ed25519.Verify(pub, message, sig) Try / catch
if err := ed25519.Verify(pub, message, sig); err != nil {
if strings.Contains(err.Error(), "bad signature length") {
return fmt.Errorf("received %d-byte sig; expected raw 64-byte Ed25519, not DER", len(sig))
}
return err
} Prevention
- Decode hex/base64 signatures at the boundary and assert length 64.
- Remember Ed25519 uses raw R||S, not ASN.1 DER.
- Validate before calling Verify to give clear errors.
When it happens
Trigger: Calling Verify / VerifyPH / VerifyCtx with sig of length != 64 — e.g. DER-encoded signature, 96-byte concatenated form, truncated bytes, hex string.
Common situations: Passing an ASN.1 DER ECDSA-style signature to Ed25519 verify; passing hex/base64 strings instead of decoded bytes; truncation in transit; off-by-one slice handling.
Related errors
- ed25519: bad seed length: {l}
- ed25519: bad private key length: {l}
- ed25519: bad public key length: {l}
- ed25519: bad Ed25519ph message hash length: {l}
- ed25519: bad Ed25519ph context length: {l}
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/9cb9791056ee2c9f.
Report an issue: GitHub.