golang/go · error
mlkem: invalid seed length
Error message
mlkem: invalid seed length
What it means
Thrown by newKeyFromSeed (via NewDecapsulationKey768) when the seed is not exactly SeedSize (64 bytes = 32-byte d || 32-byte z). This is the approved production key-generation path; the seed must be uniformly random and exactly seed-sized.
Source
Thrown at src/crypto/internal/fips140/mlkem/mlkem768.go:205
// exclusively for use in tests.
func GenerateKeyInternal768(d, z *[32]byte) *DecapsulationKey768 {
fipsSelfTest()
dk := &DecapsulationKey768{}
kemKeyGen(dk, d, z)
return dk
}
// NewDecapsulationKey768 parses a decapsulation key from a 64-byte
// seed in the "d || z" form. The seed must be uniformly random.
func NewDecapsulationKey768(seed []byte) (*DecapsulationKey768, error) {
// The actual logic is in a separate function to outline this allocation.
dk := &DecapsulationKey768{}
return newKeyFromSeed(dk, seed)
}
func newKeyFromSeed(dk *DecapsulationKey768, seed []byte) (*DecapsulationKey768, error) {
if len(seed) != SeedSize {
return nil, errors.New("mlkem: invalid seed length")
}
d := (*[32]byte)(seed[:32])
z := (*[32]byte)(seed[32:])
kemKeyGen(dk, d, z)
fips140.RecordApproved()
return dk, nil
}
// TestingOnlyNewDecapsulationKey768 parses a decapsulation key from its expanded NIST format.
//
// Bytes() must not be called on the returned key, as it will not produce the
// original seed.
//
// This function should only be used for ACVP testing. Prefer NewDecapsulationKey768 for all
// other purposes.
func TestingOnlyNewDecapsulationKey768(b []byte) (*DecapsulationKey768, error) {
if len(b) != decapsulationKeySize768 {
return nil, errors.New("mlkem: invalid NIST decapsulation key length")View on GitHub (pinned to b6b368adc5)
Solutions
- Read exactly SeedSize (64) bytes from crypto/rand and check the read error.
- If persisting a seed, store/transport it as a fixed 64-byte blob and verify length on load.
- Do not derive the seed from a password or short entropy source; use the OS CSPRNG.
- Distinguish the 64-byte d||z seed from the 2400-byte NIST expanded format handled by TestingOnlyNewDecapsulationKey768.
Example fix
// before
seed := make([]byte, 32) // wrong: only d
dk, err := mlkem768.NewDecapsulationKey768(seed)
// after
seed := make([]byte, mlkem768.SeedSize)
if _, err := io.ReadFull(crand.Reader, seed); err != nil { return err }
dk, err := mlkem768.NewDecapsulationKey768(seed) Defensive patterns
Strategy: validation
Validate before calling
if len(seed) != mlkem768.SeedSize {
return fmt.Errorf("seed len %d != %d", len(seed), mlkem768.SeedSize)
} Type guard
func isMLKEM768Seed(b []byte) bool { return len(b) == mlkem768.SeedSize } Try / catch
dk, err := mlkem768.NewDecapsulationKey768(seed)
if err != nil {
return fmt.Errorf("seed rejected (len=%d): %w", len(seed), err)
} Prevention
- Read the seed with io.ReadFull(crand.Reader, seed[:64]) and check the error.
- Do not derive seeds from passwords or short entropy.
- Distinguish the 64-byte seed from the NIST expanded blob format.
When it happens
Trigger: Passing a 32-byte half-seed, a 96-byte triple, a hex/base64 string instead of raw bytes, or a crypto/rand read that was short due to an ignored error.
Common situations: Confusing SeedSize (64) with the 32-byte d alone, reusing an Ed25519/X25532 seed, feeding a passphrase-derived 32 bytes, or assuming SeedSize matches the NIST expanded format length.
Related errors
- mlkem: invalid encapsulation key length
- mlkem: invalid ciphertext length
- mlkem: invalid NIST decapsulation key length
- mlkem: invalid encapsulation key length
- mlkem: invalid ciphertext length
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/aaebf4e1a439a383.
Report an issue: GitHub.