aboutsummaryrefslogtreecommitdiff
path: root/source/storage/Vault.mc
diff options
context:
space:
mode:
authorcirakg <cirakg@cirakg.xyz>2026-10-20 01:51:05 +0200
committercirakg <cirakg@cirakg.xyz>2026-10-20 01:51:05 +0200
commitbc228753bfb4a2faea540cddb20fc39ebd265db5 (patch)
treecd959eb8a037cea49282fc5cfef53bc9209efbb0 /source/storage/Vault.mc
parent81a5b903297e59d599dd0d6f580b89597630909d (diff)
feat(storage): add keyed secret fingerprints to record headers
An 8-byte HMAC of kind, type and secret (key derived from the device key) in header tag 13 lets imports find duplicates of locked entries while the watch is locked. Vault gains anyHeader() and storage(). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'source/storage/Vault.mc')
-rw-r--r--source/storage/Vault.mc19
1 files changed, 19 insertions, 0 deletions
diff --git a/source/storage/Vault.mc b/source/storage/Vault.mc
index 95f77c9..e77bbf2 100644
--- a/source/storage/Vault.mc
+++ b/source/storage/Vault.mc
@@ -51,6 +51,12 @@ class Vault {
// ---- Reading -------------------------------------------------------
+ // The underlying store (for the import buffer, which lives next to the
+ // entries and uses the same device key).
+ function storage() as Persist.Backend {
+ return _store;
+ }
+
// Entry IDs in display order (a copy).
function ids() as Array<String> {
return _ids.slice(0, null) as Array<String>;
@@ -82,6 +88,17 @@ class Vault {
return entry;
}
+ // The header of a listed entry or of a pending one ("p.<id>"), or null
+ // when it doesn't exist or is damaged. Never throws.
+ function anyHeader(id as String) as Entry? {
+ var key = _ids.indexOf(id) >= 0 ? "e." + id : (_pending.indexOf(id) >= 0 ? "p." + id : null);
+ if (key == null) {
+ return null;
+ }
+ var stored = _store.getValue(key);
+ return stored instanceof ByteArray ? Record.decodeHeader(stored) : null;
+ }
+
// The full entry with its secret. Throws NOT_FOUND, LOCKED (locked entry
// while the session is locked) or DAMAGED. Call wipeSecrets() when done.
function open(id as String) as Entry {
@@ -109,6 +126,7 @@ class Vault {
throw new VaultError(VaultError.LIMIT, "at most " + MAX_ENTRIES + " entries");
}
entry.id = newId();
+ entry.fingerprint = keyManager.fingerprint(entry);
if (entry.created == 0) {
entry.created = Clock.nowUnix(0);
}
@@ -130,6 +148,7 @@ class Vault {
function update(entry as Entry) as Void {
var record = recordFor(entry.id);
checkStorable(entry);
+ entry.fingerprint = keyManager.fingerprint(entry);
if ((record != null && Record.keyRef(record) == Record.KEY_MASTER) || entry.locked) {
session.keys(); // throws LOCKED
}