golang/go · error
ed25519: bad seed length: {l}
Error message
ed25519: bad seed length: {l} What it means
Returned by NewPrivateKeyFromSeed when the seed is not exactly seedSize (32) bytes. Ed25519 per RFC 8032 fixes the seed at 32 bytes; the seed is hashed with SHA-512 internally to derive the scalar and prefix, so any other length is unrecoverable.
Source
Thrown at src/crypto/internal/fips140/ed25519/ed25519.go:84
}
func generateKey(priv *PrivateKey) (*PrivateKey, error) {
fips140.RecordApproved()
drbg.Read(priv.seed[:])
precomputePrivateKey(priv)
fipsPCT(priv)
return priv, nil
}
func NewPrivateKeyFromSeed(seed []byte) (*PrivateKey, error) {
priv := &PrivateKey{}
return newPrivateKeyFromSeed(priv, seed)
}
func newPrivateKeyFromSeed(priv *PrivateKey, seed []byte) (*PrivateKey, error) {
fips140.RecordApproved()
if l := len(seed); l != seedSize {
return nil, errors.New("ed25519: bad seed length: " + strconv.Itoa(l))
}
copy(priv.seed[:], seed)
precomputePrivateKey(priv)
return priv, nil
}
func precomputePrivateKey(priv *PrivateKey) {
hs := sha512.New()
hs.Write(priv.seed[:])
h := hs.Sum(make([]byte, 0, sha512Size))
s, err := priv.s.SetBytesWithClamping(h[:32])
if err != nil {
panic("ed25519: internal error: setting scalar failed")
}
A := (&edwards25519.Point{}).ScalarBaseMult(s)
copy(priv.pub[:], A.Bytes())
View on GitHub (pinned to b6b368adc5)
Solutions
- Supply exactly 32 raw bytes as the seed.
- If you have a hex string, hex-decode it first (hex.DecodeString) and check len==32 before calling.
- If you have a 64-byte Ed25519 private key, call NewPrivateKey (not FromSeed).
Example fix
// before
seed, _ := hex.DecodeString(seedHex) // wrong length
priv, err := ed25519.NewPrivateKeyFromSeed(seed)
// after
seed, err := hex.DecodeString(seedHex)
if err != nil { return err }
if len(seed) != 32 { return fmt.Errorf("seed must be 32 bytes, got %d", len(seed)) }
priv, err := ed25519.NewPrivateKeyFromSeed(seed) Defensive patterns
Strategy: validation
Validate before calling
const ed25519SeedSize = 32
if len(seed) != ed25519SeedSize {
return nil, fmt.Errorf("ed25519 seed must be %d bytes, got %d", ed25519SeedSize, len(seed))
}
return ed25519.NewPrivateKeyFromSeed(seed) Try / catch
priv, err := ed25519.NewPrivateKeyFromSeed(seed)
if err != nil {
if strings.Contains(err.Error(), "bad seed length") {
return fmt.Errorf("rejecting seed of wrong length: %w", err)
}
return err
} Prevention
- Always decode hex/base64 before passing key material.
- Wrap key import in a helper that asserts length and returns a typed error.
- Distinguish seed (32B) from private key (64B) at the API boundary.
When it happens
Trigger: Calling fips140/ed25519.NewPrivateKeyFromSeed(seed) with a seed slice whose length is not 32 (e.g. 16, 64, base64-decoded to 44, hex string instead of bytes).
Common situations: Passing a hex- or base64-encoded seed without decoding; reusing an Ed25519 private-key blob (64 bytes) as the seed; truncated seed from a misconfigured KMS or env var; copying a 'seed' that is actually the SHA-512 expanded form.
Related errors
- 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}
- ed25519: bad Ed25519ctx context length: {l}
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/6efa88b2cc6e796e.
Report an issue: GitHub.