moonD4rk/HackBrowserData · error
encrypted_key too short: %d bytes
Error message
encrypted_key too short: %d bytes
What it means
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.
Source
Thrown at masterkey/retriever_windows.go:36
func (r *DPAPIRetriever) RetrieveKey(hints Hints) ([]byte, error) {
data, err := os.ReadFile(hints.LocalStatePath)
if err != nil {
return nil, fmt.Errorf("read Local State: %w", err)
}
encryptedKey := gjson.GetBytes(data, "os_crypt.encrypted_key")
if !encryptedKey.Exists() {
return nil, fmt.Errorf("os_crypt.encrypted_key not found in Local State")
}
keyBytes, err := base64.StdEncoding.DecodeString(encryptedKey.String())
if err != nil {
return nil, fmt.Errorf("base64 decode encrypted_key: %w", err)
}
const dpapiPrefix = "DPAPI"
if len(keyBytes) <= len(dpapiPrefix) {
return nil, fmt.Errorf("encrypted_key too short: %d bytes", len(keyBytes))
}
if string(keyBytes[:len(dpapiPrefix)]) != dpapiPrefix {
return nil, fmt.Errorf("encrypted_key unexpected prefix: got %q, want %q", keyBytes[:len(dpapiPrefix)], dpapiPrefix)
}
masterKey, err := crypto.DecryptDPAPI(keyBytes[len(dpapiPrefix):])
if err != nil {
return nil, fmt.Errorf("DPAPI decrypt: %w", err)
}
return masterKey, nil
}
// DefaultRetrievers wires the Windows tiers: DPAPI for v10, ABE for v20 (Chrome 127+, via reflective
// injection). Both run — a profile upgraded from pre-v127 mixes v10+v20 and needs both (issue #578).
func DefaultRetrievers() Retrievers {
return Retrievers{
V10: &DPAPIRetriever{},
V20: &ABERetriever{},View on GitHub (pinned to 0503d04d7a)
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.
Example fix
// before: trusting the decoded length blindly
keyBytes, _ := base64.StdEncoding.DecodeString(encryptedKey.String())
// after: validate before use
keyBytes, err := base64.StdEncoding.DecodeString(encryptedKey.String())
if err != nil || len(keyBytes) <= 5 {
return nil, fmt.Errorf("invalid encrypted_key (len=%d)", len(keyBytes))
} Defensive patterns
Strategy: validation
Validate before calling
raw, _ := base64.StdEncoding.DecodeString(gjson.GetBytes(data, "os_crypt.encrypted_key").String())
if len(raw) <= 5+32 { return errors.New("encrypted_key implausibly short for a DPAPI blob") } Type guard
func looksLikeDPAPIBlob(b []byte) bool { return len(b) > 5 && bytes.HasPrefix(b, []byte("DPAPI")) } Try / catch
key, err := retriever.RetrieveKey(hints)
if err != nil && strings.Contains(err.Error(), "too short") {
// replace fixture/corrupt Local State, then retry
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- encrypted_key unexpected prefix: got %q, want %q
- base64 decode encrypted_key: %w
- DPAPI not supported on this platform
- abe: encrypted key too short: %d bytes
- abe: unexpected prefix: got %q, want %q
AI-assisted analysis of moonD4rk/HackBrowserData@0503d04d7a (2026-09-06).
Data as JSON: /api/errors/0d2cb49a7aa1c906.
Report an issue: GitHub.