{"record":{"id":"0d2cb49a7aa1c906","repo":"moonD4rk/HackBrowserData","slug":"encrypted-key-too-short-d-bytes","errorCode":null,"errorMessage":"encrypted_key too short: %d bytes","messagePattern":"encrypted_key too short: (.+?) bytes","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"masterkey/retriever_windows.go","lineNumber":36,"sourceCode":"func (r *DPAPIRetriever) RetrieveKey(hints Hints) ([]byte, error) {\n\tdata, err := os.ReadFile(hints.LocalStatePath)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"read Local State: %w\", err)\n\t}\n\n\tencryptedKey := gjson.GetBytes(data, \"os_crypt.encrypted_key\")\n\tif !encryptedKey.Exists() {\n\t\treturn nil, fmt.Errorf(\"os_crypt.encrypted_key not found in Local State\")\n\t}\n\n\tkeyBytes, err := base64.StdEncoding.DecodeString(encryptedKey.String())\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"base64 decode encrypted_key: %w\", err)\n\t}\n\n\tconst dpapiPrefix = \"DPAPI\"\n\tif len(keyBytes) <= len(dpapiPrefix) {\n\t\treturn nil, fmt.Errorf(\"encrypted_key too short: %d bytes\", len(keyBytes))\n\t}\n\tif string(keyBytes[:len(dpapiPrefix)]) != dpapiPrefix {\n\t\treturn nil, fmt.Errorf(\"encrypted_key unexpected prefix: got %q, want %q\", keyBytes[:len(dpapiPrefix)], dpapiPrefix)\n\t}\n\n\tmasterKey, err := crypto.DecryptDPAPI(keyBytes[len(dpapiPrefix):])\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"DPAPI decrypt: %w\", err)\n\t}\n\treturn masterKey, nil\n}\n\n// DefaultRetrievers wires the Windows tiers: DPAPI for v10, ABE for v20 (Chrome 127+, via reflective\n// injection). Both run — a profile upgraded from pre-v127 mixes v10+v20 and needs both (issue #578).\nfunc DefaultRetrievers() Retrievers {\n\treturn Retrievers{\n\t\tV10: &DPAPIRetriever{},\n\t\tV20: &ABERetriever{},","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/moonD4rk/HackBrowserData/blob/0503d04d7a8d0379d060268a74f1b149e5a0aad5/masterkey/retriever_windows.go#L18-L54","documentation":"After base64-decoding os_crypt.encrypted_key, RetrieveKey requires more bytes than the 5-byte 'DPAPI' prefix so it can slice safely. This error means the decoded key blob is 5 bytes or fewer, i.e. structurally invalid — a real Chrome encrypted_key is 'DPAPI' plus a DPAPI blob of dozens of bytes.","triggerScenarios":"base64 decoding succeeded but produced <=5 bytes: the encrypted_key field held a trivially short string (empty, a placeholder like 'AAAA', or a truncated value).","commonSituations":"Fixture/test Local State files with dummy values; manual edits that truncated the key; copying only part of the value out of the JSON; a fresh or reset profile where the key was never written properly.","solutions":["Inspect the raw os_crypt.encrypted_key value — it should decode to tens/hundreds of bytes starting with 'DPAPI'.","Use a Local State written by a real Chrome/Chromium install that has saved at least one password or cookie.","If testing, replace placeholder keys with realistic-length dummy blobs prefixed with 'DPAPI'.","Check that no post-processing step (JSON copy, regex extraction) truncated the string."],"exampleFix":"// before: trusting the decoded length blindly\nkeyBytes, _ := base64.StdEncoding.DecodeString(encryptedKey.String())\n// after: validate before use\nkeyBytes, err := base64.StdEncoding.DecodeString(encryptedKey.String())\nif err != nil || len(keyBytes) <= 5 {\n\treturn nil, fmt.Errorf(\"invalid encrypted_key (len=%d)\", len(keyBytes))\n}","handlingStrategy":"validation","validationCode":"raw, _ := base64.StdEncoding.DecodeString(gjson.GetBytes(data, \"os_crypt.encrypted_key\").String())\nif len(raw) <= 5+32 { return errors.New(\"encrypted_key implausibly short for a DPAPI blob\") }","typeGuard":"func looksLikeDPAPIBlob(b []byte) bool { return len(b) > 5 && bytes.HasPrefix(b, []byte(\"DPAPI\")) }","tryCatchPattern":"key, err := retriever.RetrieveKey(hints)\nif err != nil && strings.Contains(err.Error(), \"too short\") {\n\t// replace fixture/corrupt Local State, then retry\n}","preventionTips":["Use Local State files from real browser installs, not placeholders.","Regex-extracting the key by hand often truncates — parse JSON instead.","Log decoded blob length during triage."],"tags":["dpapi","chromium","validation","windows"],"backgroundTag":"value-out-of-range","analyzedSha":"0503d04d7a8d0379d060268a74f1b149e5a0aad5","analyzedAt":"2026-09-06T13:38:28.707Z","contentChangedAt":"2026-09-06T13:38:28.707Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}