{"record":{"id":"b8de290003485baf","repo":"golang/go","slug":"hkdf-requested-key-length-too-large","errorCode":null,"errorMessage":"hkdf: requested key length too large","messagePattern":"hkdf: requested key length too large","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/hkdf/hkdf.go","lineNumber":50,"sourceCode":"\treturn hkdf.Extract(fh, secret, salt), nil\n}\n\n// Expand derives a key from the given hash, key, and optional context info,\n// returning a []byte of length keyLength that can be used as cryptographic key.\n// The extraction step is skipped.\n//\n// The key should have been generated by [Extract], or be a uniformly\n// random or pseudorandom cryptographically strong key. See RFC 5869, Section\n// 3.3. Most common scenarios will want to use [Key] instead.\nfunc Expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLength int) ([]byte, error) {\n\tfh := fips140hash.UnwrapNew(h)\n\tif err := checkFIPS140Only(fh, pseudorandomKey); err != nil {\n\t\treturn nil, err\n\t}\n\n\tlimit := fh().Size() * 255\n\tif keyLength > limit {\n\t\treturn nil, errors.New(\"hkdf: requested key length too large\")\n\t}\n\n\treturn hkdf.Expand(fh, pseudorandomKey, info, keyLength), nil\n}\n\n// Key derives a key from the given hash, secret, salt and context info,\n// returning a []byte of length keyLength that can be used as cryptographic key.\n// Salt and info can be nil.\nfunc Key[Hash hash.Hash](h func() Hash, secret, salt []byte, info string, keyLength int) ([]byte, error) {\n\tfh := fips140hash.UnwrapNew(h)\n\tif err := checkFIPS140Only(fh, secret); err != nil {\n\t\treturn nil, err\n\t}\n\n\tlimit := fh().Size() * 255\n\tif keyLength > limit {\n\t\treturn nil, errors.New(\"hkdf: requested key length too large\")\n\t}","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/hkdf/hkdf.go#L32-L68","documentation":"Thrown by hkdf.Expand (hkdf.go:50) when the requested keyLength exceeds fh().Size() * 255. HKDF-Expand produces at most 255 blocks (RFC 5869 §2.3); requesting more is a protocol-violating input. The limit depends on the chosen hash's output size.","triggerScenarios":"Calling hkdf.Expand(sha256.New, prk, info, keyLength) with keyLength > 255*32 (8160 bytes for SHA-256) — or any hash where keyLength > 255*Size. Common when keyLength is computed from a config or derived value without an upper-bound check.","commonSituations":"Deriving very long output for a custom KDF chain; keyLength sourced from a length field in an untrusted message; off-by units (bits vs bytes) producing a huge number.","solutions":["Cap keyLength to <= 255 * hashSize before calling Expand; for SHA-256 that is 8160 bytes.","Fix unit confusion — HKDF takes keyLength in bytes, not bits.","If you need more keying material than the limit, derive intermediate keys and chain HKDF rounds."],"exampleFix":"// before\nkey, err := hkdf.Expand(sha256.New, prk, \"\", 1<<20) // > 8160 -> error 255\n\n// after\nconst limit = sha256.Size * 255 // 8160\nwant := 64\nif want > limit { return fmt.Errorf(\"key too long\") }\nkey, err := hkdf.Expand(sha256.New, prk, \"\", want)","handlingStrategy":"validation","validationCode":"limit := sha256.Size * 255 // example for SHA-256\nif keyLength > limit || keyLength <= 0 {\n    return fmt.Errorf(\"keyLength must be in [1, %d]\", limit)\n}","typeGuard":"func hkdfExpandLenOK(hashSize, keyLength int) bool {\n    return keyLength > 0 && keyLength <= hashSize*255\n}","tryCatchPattern":null,"preventionTips":["Treat keyLength as bytes, not bits.","Cap derived key length at 255 * hashSize; chain HKDF rounds for more material.","Bound keyLength when it comes from untrusted input."],"tags":["go","crypto","hkdf","validation"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}