moonD4rk/HackBrowserData · error
base64 decode encrypted_key: %w
Error message
base64 decode encrypted_key: %w
What it means
RetrieveKey in masterkey/retriever_windows.go reads Chrome's Local State file and base64-decodes the os_crypt.encrypted_key value. This error means the stored value is not valid standard base64, so DecodeString failed before any DPAPI work could start. It indicates the Local State JSON is corrupt, truncated, or the field was extracted/modified incorrectly.
Source
Thrown at masterkey/retriever_windows.go:31
)
// 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)
}
return masterKey, nil
}
// DefaultRetrievers wires the Windows tiers: DPAPI for v10, ABE for v20 (Chrome 127+, via reflectiveView on GitHub (pinned to 0503d04d7a)
Solutions
- Re-open the target browser so Chrome rewrites a clean Local State, then retry.
- Verify os_crypt.encrypted_key in the Local State JSON is a single-line standard-base64 string with no whitespace or escapes (e.g. with `jq -r '.os_crypt.encrypted_key'` and piping to `base64 -d`).
- Delete the corrupt profile's Local State and let the browser regenerate it (note: cookies become undecryptable until re-login).
- Confirm you are pointing hints.LocalStatePath at the correct profile's Local State, not a different browser's file with a different schema.
Example fix
// before (URL-safe base64 value fails StdEncoding)
keyBytes, err := base64.StdEncoding.DecodeString(encryptedKey.String())
// after (tolerate URL-safe alphabet too)
keyBytes, err := base64.StdEncoding.WithPadding(base64.StdPadding).DecodeString(strings.NewReplacer("-", "+", "_", "/").Replace(encryptedKey.String())) Defensive patterns
Strategy: validation
Validate before calling
v := gjson.GetBytes(localState, "os_crypt.encrypted_key").String()
if v == "" { return errors.New("encrypted_key missing/empty") }
if _, err := base64.StdEncoding.DecodeString(v); err != nil {
return fmt.Errorf("encrypted_key not valid std base64: %w", err)
} Type guard
func validBase64(s string) bool {
_, err := base64.StdEncoding.DecodeString(s)
return s != "" && err == nil
} Try / catch
key, err := retriever.RetrieveKey(hints)
var b64Err *base64.CorruptInputError
if err != nil && errors.As(err, &b64Err) {
// regenerate Local State or fall back to ABE retriever
} Prevention
- Never hand-edit Local State; let the browser write it.
- Validate base64 with a quick decode before downstream DPAPI work.
- Point LocalStatePath at the exact profile directory.
When it happens
Trigger: os.ReadFile succeeded on Local State and gjson found os_crypt.encrypted_key, but base64.StdEncoding.DecodeString on the value failed (illegal characters, wrong padding, whitespace, or the value was double-escaped/JSON-mangled).
Common situations: A partially written or corrupted Local State from a crashed browser; a hand-edited or tool-modified Local State; running against a fake/fixture Local State with placeholder values; the encrypted_key containing URL-safe base64 characters (-/_) instead of standard base64.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- encrypted_key too short: %d bytes
- encrypted_key unexpected prefix: got %q, want %q
- DPAPI not supported on this platform
- abe: base64 decode: %w
- read Local State: %w
AI-assisted analysis of moonD4rk/HackBrowserData@0503d04d7a (2026-09-06).
Data as JSON: /api/errors/4712e0c8da94e98a.
Report an issue: GitHub.