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:
@@ -69,12 +69,16 @@ func (d Dump) WriteJSON(w io.Writer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadJSON parses a Dump from r.
|
||||
// ReadJSON parses a Dump from r and rejects schema versions this build cannot interpret —
|
||||
// silent misparse of a future v2 schema is worse than a clear error.
|
||||
func ReadJSON(r io.Reader) (Dump, error) {
|
||||
var d Dump
|
||||
dec := json.NewDecoder(r)
|
||||
if err := dec.Decode(&d); err != nil {
|
||||
return Dump{}, fmt.Errorf("decode dump: %w", err)
|
||||
}
|
||||
if d.Version != DumpVersion {
|
||||
return Dump{}, fmt.Errorf("unsupported dump version %q (this build expects %q)", d.Version, DumpVersion)
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package keyretriever
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestReadJSON_RejectsUnknownVersion(t *testing.T) {
|
||||
input := bytes.NewBufferString(`{"version":"99","created_at":"2026-05-16T00:00:00Z","host":{"os":"linux","arch":"amd64"},"vaults":[]}`)
|
||||
_, err := ReadJSON(input)
|
||||
if err == nil {
|
||||
t.Fatal("ReadJSON should reject unknown version, got nil error")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "unsupported dump version") {
|
||||
t.Errorf("error should mention unsupported version, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadJSON_RejectsMissingVersion(t *testing.T) {
|
||||
input := bytes.NewBufferString(`{"created_at":"2026-05-16T00:00:00Z","host":{"os":"linux","arch":"amd64"},"vaults":[]}`)
|
||||
_, err := ReadJSON(input)
|
||||
if err == nil {
|
||||
t.Fatal("ReadJSON should reject empty version, got nil error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadJSON_AcceptsCurrentVersion(t *testing.T) {
|
||||
d := NewDump()
|
||||
var buf bytes.Buffer
|
||||
if err := d.WriteJSON(&buf); err != nil {
|
||||
t.Fatalf("WriteJSON: %v", err)
|
||||
}
|
||||
parsed, err := ReadJSON(&buf)
|
||||
if err != nil {
|
||||
t.Fatalf("ReadJSON: %v", err)
|
||||
}
|
||||
if parsed.Version != DumpVersion {
|
||||
t.Errorf("Version = %q, want %q", parsed.Version, DumpVersion)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package keyretriever
|
||||
|
||||
// StaticProvider returns pre-supplied master-key bytes; used by cross-host workflows where keys come
|
||||
// from a Dump rather than platform-native retrieval. RetrieveKey ignores Hints and returns the stored
|
||||
// bytes verbatim; an empty StaticProvider returns (nil, nil), the "not applicable" signal accepted
|
||||
// by NewMasterKeys when a tier was not present in the source Dump.
|
||||
type StaticProvider struct {
|
||||
key []byte
|
||||
}
|
||||
|
||||
// NewStaticProvider wraps key bytes as a KeyRetriever. A nil/empty key produces a provider that
|
||||
// reports the tier as unavailable (nil, nil) rather than returning a zero-length key.
|
||||
func NewStaticProvider(key []byte) *StaticProvider {
|
||||
return &StaticProvider{key: key}
|
||||
}
|
||||
|
||||
// RetrieveKey returns the stored key bytes, ignoring Hints.
|
||||
func (p *StaticProvider) RetrieveKey(_ Hints) ([]byte, error) {
|
||||
if len(p.key) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return p.key, nil
|
||||
}
|
||||
Reference in New Issue
Block a user