mirror of
https://github.com/moonD4rk/HackBrowserData.git
synced 2026-05-19 18:58:03 +02:00
feat(keys): add --keys flag to dump for cross-host decryption
Consumer side of the cross-host key workflow (pairs with #599). ApplyDump wires StaticProviders from a dump.json into matching browsers, so dump --keys f.json -p /copied/data decrypts without native retrievers.
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
package browser
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
|
||||
"github.com/moond4rk/hackbrowserdata/crypto/keyretriever"
|
||||
"github.com/moond4rk/hackbrowserdata/log"
|
||||
)
|
||||
@@ -69,3 +71,56 @@ func groupByInstallation(browsers []Browser) (map[string]*installGroup, []string
|
||||
}
|
||||
return groups, order
|
||||
}
|
||||
|
||||
// ApplyDump installs master keys from dump onto matching browsers, replacing each browser's default
|
||||
// platform-native retrievers with StaticProviders backed by the Dump's bytes. Matching is by
|
||||
// (BrowserName, UserDataDir) — the same key BuildDump groups by. When exact match fails (commonly a
|
||||
// cross-host path mismatch: Windows backslash vs POSIX, or a relocated User Data dir via -p), falls
|
||||
// back to the sole vault for that browser name when one exists. Browsers without a matching vault
|
||||
// are warned and left untouched; non-KeyManager browsers (Firefox/Safari) are skipped silently.
|
||||
func ApplyDump(browsers []Browser, dump keyretriever.Dump) {
|
||||
if dump.Host.OS != "" && dump.Host.OS != runtime.GOOS {
|
||||
log.Infof("apply-keys: dump created on %s/%s; current host is %s/%s",
|
||||
dump.Host.OS, dump.Host.Arch, runtime.GOOS, runtime.GOARCH)
|
||||
}
|
||||
vaultIndex := make(map[string]*keyretriever.Vault, len(dump.Vaults))
|
||||
vaultsByBrowser := make(map[string][]*keyretriever.Vault)
|
||||
for i := range dump.Vaults {
|
||||
v := &dump.Vaults[i]
|
||||
vaultIndex[v.Browser+"|"+v.UserDataDir] = v
|
||||
vaultsByBrowser[v.Browser] = append(vaultsByBrowser[v.Browser], v)
|
||||
}
|
||||
for _, b := range browsers {
|
||||
km, ok := b.(KeyManager)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
v, found := vaultIndex[b.BrowserName()+"|"+b.UserDataDir()]
|
||||
if !found {
|
||||
if candidates := vaultsByBrowser[b.BrowserName()]; len(candidates) == 1 {
|
||||
v = candidates[0]
|
||||
log.Infof("apply-keys: %s/%s using sole vault for browser (dump path %q != local %q)",
|
||||
b.BrowserName(), b.ProfileName(), v.UserDataDir, b.UserDataDir())
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
log.Warnf("apply-keys: %s/%s no matching vault in dump", b.BrowserName(), b.ProfileName())
|
||||
continue
|
||||
}
|
||||
km.SetKeyRetrievers(keyretriever.Retrievers{
|
||||
V10: maybeStaticProvider(v.Keys.V10),
|
||||
V11: maybeStaticProvider(v.Keys.V11),
|
||||
V20: maybeStaticProvider(v.Keys.V20),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// maybeStaticProvider wraps non-empty key bytes as a StaticProvider; an empty/nil key returns nil
|
||||
// to preserve the "tier not applicable" signal NewMasterKeys expects.
|
||||
func maybeStaticProvider(key []byte) keyretriever.KeyRetriever {
|
||||
if len(key) == 0 {
|
||||
return nil
|
||||
}
|
||||
return keyretriever.NewStaticProvider(key)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user