mirror of
https://github.com/moonD4rk/HackBrowserData.git
synced 2026-06-04 19:48:01 +02:00
refactor(browser): split installation and profile abstractions (#603)
* refactor(browser): split installation and profile abstractions A Chromium installation shares one master key across its profiles, but modeling each profile as its own Browser re-derived the key per profile. Browser now represents one installation holding its profiles and derives the key once; new types.Profile/ExtractResult/CountResult carry per-profile results. * style: gofumpt safari_test.go * test(chromium): rename shadowed loop var to path
This commit is contained in:
+33
-53
@@ -7,77 +7,57 @@ import (
|
||||
"github.com/moond4rk/hackbrowserdata/log"
|
||||
)
|
||||
|
||||
// BuildDump exports per-installation master keys; profiles sharing (Browser, UserDataDir) collapse into one Vault.
|
||||
// Browsers without KeyManager (Firefox/Safari) are skipped. ExportKeys is invoked exactly once per installation
|
||||
// regardless of profile count or success. Partial results (e.g. V10 retrieved, V20 failed) keep the usable tiers
|
||||
// rather than discarding the vault, matching getMasterKeys' behavior on the extraction path — a Chrome 127+
|
||||
// profile mixes v10 + v20 ciphertexts and a v20-only failure must not erase a usable v10 key.
|
||||
// BuildDump exports per-installation master keys. Each Browser is one installation,
|
||||
// so this is a straight one-Vault-per-installation map: ExportKeys is invoked once
|
||||
// per installation. Installations without KeyManager (Firefox/Safari) are skipped.
|
||||
// Partial results (e.g. V10 retrieved, V20 failed) keep the usable tiers rather than
|
||||
// discarding the vault — a Chrome 127+ profile mixes v10 + v20 ciphertexts and a
|
||||
// v20-only failure must not erase a usable v10 key.
|
||||
func BuildDump(browsers []Browser) keyretriever.Dump {
|
||||
dump := keyretriever.NewDump()
|
||||
groups, order := groupByInstallation(browsers)
|
||||
for _, key := range order {
|
||||
g := groups[key]
|
||||
keys, err := g.km.ExportKeys()
|
||||
for _, b := range browsers {
|
||||
km, ok := b.(KeyManager)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
keys, err := km.ExportKeys()
|
||||
if err != nil {
|
||||
status := "partial"
|
||||
if !keys.HasAny() {
|
||||
status = "failed"
|
||||
}
|
||||
log.Warnf("dump-keys: %s/%s %s: %v", g.browser, g.profiles[0], status, err)
|
||||
log.Warnf("dump-keys: %s %s: %v", b.BrowserName(), status, err)
|
||||
}
|
||||
if !keys.HasAny() {
|
||||
continue
|
||||
}
|
||||
dump.Vaults = append(dump.Vaults, keyretriever.Vault{
|
||||
Browser: g.browser,
|
||||
UserDataDir: g.userDataDir,
|
||||
Profiles: g.profiles,
|
||||
Browser: b.BrowserName(),
|
||||
UserDataDir: b.UserDataDir(),
|
||||
Profiles: profileNames(b),
|
||||
Keys: keys,
|
||||
})
|
||||
}
|
||||
return dump
|
||||
}
|
||||
|
||||
type installGroup struct {
|
||||
browser, userDataDir string
|
||||
km KeyManager
|
||||
profiles []string
|
||||
}
|
||||
|
||||
// groupByInstallation collects browsers into per-installation groups keyed by (BrowserName, UserDataDir),
|
||||
// preserving the discovery order of the first profile in each group. Non-KeyManager browsers are skipped.
|
||||
// Doing the grouping up front (rather than checking dump.Vaults profile-by-profile) makes the resulting
|
||||
// Profiles list complete and order-independent even if the group's ExportKeys later fails.
|
||||
func groupByInstallation(browsers []Browser) (map[string]*installGroup, []string) {
|
||||
groups := make(map[string]*installGroup)
|
||||
var order []string
|
||||
for _, b := range browsers {
|
||||
km, ok := b.(KeyManager)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
key := b.BrowserName() + "|" + b.UserDataDir()
|
||||
if g, exists := groups[key]; exists {
|
||||
g.profiles = append(g.profiles, b.ProfileName())
|
||||
continue
|
||||
}
|
||||
groups[key] = &installGroup{
|
||||
browser: b.BrowserName(),
|
||||
userDataDir: b.UserDataDir(),
|
||||
km: km,
|
||||
profiles: []string{b.ProfileName()},
|
||||
}
|
||||
order = append(order, key)
|
||||
func profileNames(b Browser) []string {
|
||||
profiles := b.Profiles()
|
||||
names := make([]string, 0, len(profiles))
|
||||
for _, p := range profiles {
|
||||
names = append(names, p.Name)
|
||||
}
|
||||
return groups, order
|
||||
return names
|
||||
}
|
||||
|
||||
// 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.
|
||||
// ApplyDump installs master keys from dump onto matching installations, replacing
|
||||
// each installation's default platform-native retrievers with StaticProviders
|
||||
// backed by the Dump's bytes. Matching is by (BrowserName, UserDataDir) — the same
|
||||
// key BuildDump emits. 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. Installations without a
|
||||
// matching vault are warned and left untouched; non-KeyManager installations
|
||||
// (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",
|
||||
@@ -99,13 +79,13 @@ func ApplyDump(browsers []Browser, dump keyretriever.Dump) {
|
||||
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())
|
||||
log.Infof("apply-keys: %s using sole vault for browser (dump path %q != local %q)",
|
||||
b.BrowserName(), v.UserDataDir, b.UserDataDir())
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
log.Warnf("apply-keys: %s/%s no matching vault in dump", b.BrowserName(), b.ProfileName())
|
||||
log.Warnf("apply-keys: %s no matching vault in dump", b.BrowserName())
|
||||
continue
|
||||
}
|
||||
km.SetKeyRetrievers(keyretriever.Retrievers{
|
||||
|
||||
Reference in New Issue
Block a user