{"record":{"id":"497fc2661d915f25","repo":"golang/go","slug":"mlkem-invalid-seed-length","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/mlkem1024.go","lineNumber":146,"sourceCode":"// exclusively for use in tests.\nfunc GenerateKeyInternal1024(d, z *[32]byte) *DecapsulationKey1024 {\n\tfipsSelfTest()\n\tdk := &DecapsulationKey1024{}\n\tkemKeyGen1024(dk, d, z)\n\treturn dk\n}\n\n// NewDecapsulationKey1024 parses a decapsulation key from a 64-byte\n// seed in the \"d || z\" form. The seed must be uniformly random.\nfunc NewDecapsulationKey1024(seed []byte) (*DecapsulationKey1024, error) {\n\t// The actual logic is in a separate function to outline this allocation.\n\tdk := &DecapsulationKey1024{}\n\treturn newKeyFromSeed1024(dk, seed)\n}\n\nfunc newKeyFromSeed1024(dk *DecapsulationKey1024, seed []byte) (*DecapsulationKey1024, 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\tkemKeyGen1024(dk, d, z)\n\tfips140.RecordApproved()\n\treturn dk, nil\n}\n\n// TestingOnlyNewDecapsulationKey1024 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 NewDecapsulationKey1024 for all\n// other purposes.\nfunc TestingOnlyNewDecapsulationKey1024(b []byte) (*DecapsulationKey1024, error) {\n\tif len(b) != decapsulationKeySize1024 {\n\t\treturn nil, errors.New(\"mlkem: invalid NIST decapsulation key length\")","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/internal/fips140/mlkem/mlkem1024.go#L128-L164","documentation":"ML-KEM key generation derives the decapsulation key from a 64-byte seed split into d (32 bytes, key material) and z (32 bytes, implicit-rejection secret). NewDecapsulationKey1024 checks len(seed) == SeedSize (64) before splitting; any other length is rejected. This mirrors the d||z form mandated by FIPS 203.","triggerScenarios":"Calling mlkem.NewDecapsulationKey1024(seed) (or the 512/768 siblings) with a slice whose length is not 64 — e.g. 32 bytes, or the expanded NIST key form.","commonSituations":"Passing only d (32 bytes) instead of d||z; confusing with ML-DSA's 32-byte seed; passing the expanded key bytes (which are much larger) to this seed-based constructor; hex/base64 not decoded.","solutions":["Generate a 64-byte seed via crypto/rand and pass it whole; d and z are interleaved by the library.","To load an already-expanded NIST key, use TestingOnlyNewDecapsulationKey1024 instead.","Decode hex/base64 before calling and assert the decoded length is 64."],"exampleFix":"// before\nseed := make([]byte, 32)  // missing z\ndk, err := mlkem.NewDecapsulationKey1024(seed)\n\n// after\nvar seed [mlkem.SeedSize]byte\nio.ReadFull(rand.Reader, seed[:])\ndk, err := mlkem.NewDecapsulationKey1024(seed[:])","handlingStrategy":"validation","validationCode":"if len(seed) != mlkem.SeedSize { // 64\n    return fmt.Errorf(\"mlkem seed must be %d bytes, got %d\", mlkem.SeedSize, len(seed))\n}","typeGuard":"func isMLKEMSeed(seed *[64]byte) bool { return seed != nil }","tryCatchPattern":null,"preventionTips":["Type the seed as [64]byte so length is compile-time enforced.","Generate seeds only via crypto/rand into the full 64-byte buffer.","Use TestingOnlyNewDecapsulationKey1024 for expanded NIST keys, not the seed API."],"tags":["crypto","mlkem","fips","validation","input-length"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}