moonD4rk/HackBrowserData · error
os_crypt.encrypted_key not found in Local State
Error message
os_crypt.encrypted_key not found in Local State
What it means
Local State was read successfully, but the JSON path os_crypt.encrypted_key does not exist. Chrome stores the DPAPI-encrypted AES key there; without it the V10 key cannot be derived. This indicates a malformed, truncated, or very old/unusual Local State file.
Source
Thrown at masterkey/retriever_windows.go:26
"os"
"github.com/tidwall/gjson"
"github.com/moond4rk/hackbrowserdata/crypto"
)
// DPAPIRetriever unwraps Chrome's Local State os_crypt.encrypted_key via Windows DPAPI.
type DPAPIRetriever struct{}
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)View on GitHub (pinned to 0503d04d7a)
Solutions
- Point hints.LocalStatePath at the User Data root's 'Local State' file (not a profile subfolder) and confirm the JSON contains os_crypt.encrypted_key: type "Local State" | findstr encrypted_key
- Launch Chrome once and let it encrypt cookies, which creates the encrypted_key entry, then retry
- If the file is truncated, close Chrome, restore the file (or delete and let Chrome rebuild it), then re-run
- Check file size — a 0-byte or tiny Local State means corruption; re-copy from a healthy profile backup
Example fix
// before
Hints{LocalStatePath: userDataDir + "\\Default\\Local State"}
// after
Hints{LocalStatePath: userDataDir + "\\Local State"} // User Data root, not the Default profile Defensive patterns
Strategy: validation
Validate before calling
data, err := os.ReadFile(localStatePath)
if err == nil && !gjson.GetBytes(data, "os_crypt.encrypted_key").Exists() {
// encrypted_key missing — file corrupt, wrong file, or profile never encrypted cookies
} Try / catch
key, err := dpapiRetriever.RetrieveKey(hints)
if err != nil && strings.Contains(err.Error(), "os_crypt.encrypted_key not found") {
// fall back to ABE (v20) tier or restore the Local State file
} Prevention
- Validate Local State JSON contains os_crypt.encrypted_key before attempting DPAPI unwrap
- Use the User Data root 'Local State' file, not per-profile JSON files
- Run the browser once on a fresh profile so encrypted_key is generated
- Watch for truncated/0-byte files after crashes or OneDrive sync and restore from backup
When it happens
Trigger: gjson.GetBytes(data, "os_crypt.encrypted_key") returns !Exists(): the key is absent from the JSON, the file is empty/corrupt/truncated, or it is not the User Data-level Local State (e.g. a per-profile file that lacks os_crypt).
Common situations: Chrome crash or disk full left Local State truncated; pointing the hint at Default/Preferences instead of Local State; new profile never used for cookie encryption; Chromium forks with a different os_crypt layout; file partially synced by OneDrive/roaming.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- read Local State: %w
- DPAPI not supported on this platform
- abe: Local State has no app_bound_encrypted_key
- abe: read Local State: %w
- abe: base64 decode: %w
AI-assisted analysis of moonD4rk/HackBrowserData@0503d04d7a (2026-09-06).
Data as JSON: /api/errors/8ab79e69bcc411f5.
Report an issue: GitHub.