moonD4rk/HackBrowserData · error
DPAPI decrypt: %w
Error message
DPAPI decrypt: %w
What it means
This wraps a failure from crypto.DecryptDPAPI, which calls the Windows DPAPI CryptUnprotectData API on the bytes following the 'DPAPI' prefix. DPAPI only succeeds when the blob was protected under the same Windows user (and, for machine-scope, the same machine), so failure means the master key could not be decrypted in this context.
Source
Thrown at masterkey/retriever_windows.go:44
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
- Run the tool as the same Windows user account that owns the browser profile (impersonate or log in as that user).
- Use machine-context DPAPI recovery options or the user's password via DPAPI backup-key recovery when off-box analysis is required.
- Re-open the browser on the original machine/user so Chrome can regenerate a decryptable key (existing saved data re-encrypts on next use).
- If corrupt-blob is suspected, replace the Local State with a fresh one from a healthy profile of the same user.
- For Chrome 127+ v20 cookies, ensure the ABE retriever is used — DPAPI v10 keys will not decrypt v20 payloads.
Example fix
// before: running as service account, DPAPI fails silently in context
key, err := retriever.RetrieveKey(hints)
// after: verify same-user context before calling
if cur, _ := user.Current(); cur.Username != profileOwner {
return nil, fmt.Errorf("must run as %s for DPAPI decrypt", profileOwner)
}
key, err := retriever.RetrieveKey(hints) Defensive patterns
Strategy: try-catch
Validate before calling
// Precondition checks possible before the call:
if runtime.GOOS != "windows" { return errors.New("DPAPI requires Windows") }
if cur, _ := user.Current(); cur.Username != expectedOwner {
return fmt.Errorf("run as profile owner %s", expectedOwner)
} Try / catch
key, err := retriever.RetrieveKey(hints)
if err != nil && strings.Contains(err.Error(), "DPAPI decrypt") {
// impersonate profile owner or fall back to ABE retriever for v20
} Prevention
- Run the tool as the same Windows user that owns the browser profile.
- Don't analyze copied-off profiles off-box without DPAPI backup keys.
- Keep browser and tool on the same machine for machine-scope blobs.
- Handle Chrome 127+ v20 via the ABE path instead of DPAPI.
When it happens
Trigger: DecryptDPAPI returned an error from CryptUnprotectData: running as a different Windows user than the one whose profile is being read; the Local State was copied from another machine; the DPAPI blob is corrupt; roaming-profile/credential-restore issues broke the master key.
Common situations: Security tool run via SSH, a service account, or an elevated process with a different logon session than the browser's; analyzing a copied-off profile on another machine; browser profile migrated between machines; corrupted Local State after a crash.
Related errors
- DPAPI not supported on this platform
- read Local State: %w
- os_crypt.encrypted_key not found in Local State
- base64 decode encrypted_key: %w
- encrypted_key too short: %d bytes
AI-assisted analysis of moonD4rk/HackBrowserData@0503d04d7a (2026-09-06).
Data as JSON: /api/errors/9df1db28accd8a86.
Report an issue: GitHub.