{"record":{"id":"6efa88b2cc6e796e","repo":"golang/go","slug":"ed25519-bad-seed-length-l","errorCode":null,"errorMessage":"ed25519: bad seed length: {l}","messagePattern":"ed25519: bad seed length: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/internal/fips140/ed25519/ed25519.go","lineNumber":84,"sourceCode":"}\n\nfunc generateKey(priv *PrivateKey) (*PrivateKey, error) {\n\tfips140.RecordApproved()\n\tdrbg.Read(priv.seed[:])\n\tprecomputePrivateKey(priv)\n\tfipsPCT(priv)\n\treturn priv, nil\n}\n\nfunc NewPrivateKeyFromSeed(seed []byte) (*PrivateKey, error) {\n\tpriv := &PrivateKey{}\n\treturn newPrivateKeyFromSeed(priv, seed)\n}\n\nfunc newPrivateKeyFromSeed(priv *PrivateKey, seed []byte) (*PrivateKey, error) {\n\tfips140.RecordApproved()\n\tif l := len(seed); l != seedSize {\n\t\treturn nil, errors.New(\"ed25519: bad seed length: \" + strconv.Itoa(l))\n\t}\n\tcopy(priv.seed[:], seed)\n\tprecomputePrivateKey(priv)\n\treturn priv, nil\n}\n\nfunc precomputePrivateKey(priv *PrivateKey) {\n\ths := sha512.New()\n\ths.Write(priv.seed[:])\n\th := hs.Sum(make([]byte, 0, sha512Size))\n\n\ts, err := priv.s.SetBytesWithClamping(h[:32])\n\tif err != nil {\n\t\tpanic(\"ed25519: internal error: setting scalar failed\")\n\t}\n\tA := (&edwards25519.Point{}).ScalarBaseMult(s)\n\tcopy(priv.pub[:], A.Bytes())\n","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/internal/fips140/ed25519/ed25519.go#L66-L102","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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)."],"exampleFix":"// before\nseed, _ := hex.DecodeString(seedHex) // wrong length\npriv, err := ed25519.NewPrivateKeyFromSeed(seed)\n\n// after\nseed, err := hex.DecodeString(seedHex)\nif err != nil { return err }\nif len(seed) != 32 { return fmt.Errorf(\"seed must be 32 bytes, got %d\", len(seed)) }\npriv, err := ed25519.NewPrivateKeyFromSeed(seed)","handlingStrategy":"validation","validationCode":"const ed25519SeedSize = 32\nif len(seed) != ed25519SeedSize {\n    return nil, fmt.Errorf(\"ed25519 seed must be %d bytes, got %d\", ed25519SeedSize, len(seed))\n}\nreturn ed25519.NewPrivateKeyFromSeed(seed)","typeGuard":null,"tryCatchPattern":"priv, err := ed25519.NewPrivateKeyFromSeed(seed)\nif err != nil {\n    if strings.Contains(err.Error(), \"bad seed length\") {\n        return fmt.Errorf(\"rejecting seed of wrong length: %w\", err)\n    }\n    return err\n}","preventionTips":["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."],"tags":["crypto","ed25519","fips140","validation","key-import"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}