{"record":{"id":"85cf464910524e78","repo":"golang/go","slug":"mldsa-invalid-seed-length","errorCode":null,"errorMessage":"mldsa: invalid seed length","messagePattern":"mldsa: invalid seed length","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/internal/fips140/mldsa/mldsa.go","lineNumber":143,"sourceCode":"\tfips140.RecordApproved()\n\tvar seed [32]byte\n\tdrbg.Read(seed[:])\n\tpriv := newPrivateKey(&seed, params65)\n\tfipsPCT(priv)\n\treturn priv\n}\n\nfunc GenerateKey87() *PrivateKey {\n\tfipsSelfTest()\n\tfips140.RecordApproved()\n\tvar seed [32]byte\n\tdrbg.Read(seed[:])\n\tpriv := newPrivateKey(&seed, params87)\n\tfipsPCT(priv)\n\treturn priv\n}\n\nvar errInvalidSeedLength = errors.New(\"mldsa: invalid seed length\")\n\nfunc NewPrivateKey44(seed []byte) (*PrivateKey, error) {\n\tfipsSelfTest()\n\tfips140.RecordApproved()\n\tif len(seed) != 32 {\n\t\treturn nil, errInvalidSeedLength\n\t}\n\treturn newPrivateKey((*[32]byte)(seed), params44), nil\n}\n\nfunc NewPrivateKey65(seed []byte) (*PrivateKey, error) {\n\tfipsSelfTest()\n\tfips140.RecordApproved()\n\tif len(seed) != 32 {\n\t\treturn nil, errInvalidSeedLength\n\t}\n\treturn newPrivateKey((*[32]byte)(seed), params65), nil\n}","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/internal/fips140/mldsa/mldsa.go#L125-L161","documentation":"ML-DSA (FIPS 204) key generation derives the full keypair deterministically from a 32-byte seed ξ. The constructors NewPrivateKey44/65/87 validate that the supplied seed slice is exactly 32 bytes before invoking the (expensive) key-derivation routine, refusing to run on malformed input. A wrong length therefore never reaches FIPS self-tests and is reported as a plain input error rather than a cryptographic failure.","triggerScenarios":"Calling mldsa.NewPrivateKey44(seed), NewPrivateKey65(seed), or NewPrivateKey87(seed) with a []byte whose length is not 32 (e.g. 16, 48, 64). The len(seed) != 32 branch at the top of the constructor returns errInvalidSeedLength.","commonSituations":"Passing a hex- or base64-encoded string instead of raw bytes (length 64/44 instead of 32); reading a short/truncated byte slice from a config file or env var; confusing ML-DSA's 32-byte seed with ML-KEM's 64-byte d||z seed; using crypto/rand with a wrong-sized buffer.","solutions":["Allocate a [32]byte and fill it with crypto/rand.Read(seed[:]) before calling NewPrivateKey*.","If the seed arrives hex/base64-encoded, decode it first (hex.DecodeString / base64.StdEncoding.DecodeString) and assert the decoded length is 32.","If you do not need deterministic key derivation from a seed, call GenerateKey44/65/87 instead, which internally draws the 32 bytes from the FIPS DRBG.","Add a length guard at the trust boundary (API handler, deserializer) so malformed seeds are rejected before reaching the crypto layer."],"exampleFix":"// before\nseed := []byte(\"my-fixed-passphrase-seed\")   // wrong length\npk, err := mldsa.NewPrivateKey44(seed)\n\n// after\nvar seed [32]byte\nif _, err := io.ReadFull(rand.Reader, seed[:]); err != nil { return err }\npk, err := mldsa.NewPrivateKey44(seed[:])","handlingStrategy":"validation","validationCode":"if len(seed) != 32 {\n    return fmt.Errorf(\"mldsa seed must be 32 bytes, got %d\", len(seed))\n}\npk, err := mldsa.NewPrivateKey44(seed)","typeGuard":"// seed must be exactly 32 bytes; represent it as an array to make the\n// length a compile-time property.\nfunc validateSeed(seed *[32]byte) bool { return seed != nil }","tryCatchPattern":null,"preventionTips":["Type seeds as [32]byte (not []byte) so the length is enforced at compile time.","Decode hex/base64 at the API boundary and assert decoded length before any crypto call.","Centralize seed generation in one helper that always uses crypto/rand with a [32]byte buffer."],"tags":["crypto","mldsa","fips","validation","input-length"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}