{"record":{"id":"aaebf4e1a439a383","repo":"golang/go","slug":"mlkem-invalid-seed-length-aaebf4","errorCode":null,"errorMessage":"mlkem: invalid seed length","messagePattern":"mlkem: invalid seed length","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/internal/fips140/mlkem/mlkem768.go","lineNumber":205,"sourceCode":"// exclusively for use in tests.\nfunc GenerateKeyInternal768(d, z *[32]byte) *DecapsulationKey768 {\n\tfipsSelfTest()\n\tdk := &DecapsulationKey768{}\n\tkemKeyGen(dk, d, z)\n\treturn dk\n}\n\n// NewDecapsulationKey768 parses a decapsulation key from a 64-byte\n// seed in the \"d || z\" form. The seed must be uniformly random.\nfunc NewDecapsulationKey768(seed []byte) (*DecapsulationKey768, error) {\n\t// The actual logic is in a separate function to outline this allocation.\n\tdk := &DecapsulationKey768{}\n\treturn newKeyFromSeed(dk, seed)\n}\n\nfunc newKeyFromSeed(dk *DecapsulationKey768, seed []byte) (*DecapsulationKey768, error) {\n\tif len(seed) != SeedSize {\n\t\treturn nil, errors.New(\"mlkem: invalid seed length\")\n\t}\n\td := (*[32]byte)(seed[:32])\n\tz := (*[32]byte)(seed[32:])\n\tkemKeyGen(dk, d, z)\n\tfips140.RecordApproved()\n\treturn dk, nil\n}\n\n// TestingOnlyNewDecapsulationKey768 parses a decapsulation key from its expanded NIST format.\n//\n// Bytes() must not be called on the returned key, as it will not produce the\n// original seed.\n//\n// This function should only be used for ACVP testing. Prefer NewDecapsulationKey768 for all\n// other purposes.\nfunc TestingOnlyNewDecapsulationKey768(b []byte) (*DecapsulationKey768, error) {\n\tif len(b) != decapsulationKeySize768 {\n\t\treturn nil, errors.New(\"mlkem: invalid NIST decapsulation key length\")","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/internal/fips140/mlkem/mlkem768.go#L187-L223","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nseed := make([]byte, 32) // wrong: only d\n dk, err := mlkem768.NewDecapsulationKey768(seed)\n// after\nseed := make([]byte, mlkem768.SeedSize)\nif _, err := io.ReadFull(crand.Reader, seed); err != nil { return err }\ndk, err := mlkem768.NewDecapsulationKey768(seed)","handlingStrategy":"validation","validationCode":"if len(seed) != mlkem768.SeedSize {\n    return fmt.Errorf(\"seed len %d != %d\", len(seed), mlkem768.SeedSize)\n}","typeGuard":"func isMLKEM768Seed(b []byte) bool { return len(b) == mlkem768.SeedSize }","tryCatchPattern":"dk, err := mlkem768.NewDecapsulationKey768(seed)\nif err != nil {\n    return fmt.Errorf(\"seed rejected (len=%d): %w\", len(seed), err)\n}","preventionTips":["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."],"tags":["mlkem","post-quantum","fips140","crypto","key-generation","input-validation"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}