feat: cache the master key and skip Argon2id derivation on boot - #228
Open
gmaclennan wants to merge 1 commit into
Open
feat: cache the master key and skip Argon2id derivation on boot#228gmaclennan wants to merge 1 commit into
gmaclennan wants to merge 1 commit into
Conversation
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
RangerMauve
reviewed
Aug 18, 2026
RangerMauve
left a comment
Contributor
There was a problem hiding this comment.
Looks decent overal, just a couple of questions.
gmaclennan
force-pushed
the
claude/key-manager-master-key-cache-9k40es
branch
from
August 18, 2026 21:22
abc87e2 to
bc253e6
Compare
Member
Author
|
Some performance and memory measurements on the impact of caching the derived master key. Warm boot (boot #2+ of the same install), Pixel_7a_API_34 emulator, mean of 6 boots each, running on a MacBook M2. nodejs-mobile 24 and its compile cache are constant; only the key-derivation code differs.
Ranges across the 6 samples: pre-PR 295–405 ms / 268.5–273.9 MiB; PR 30–52 ms / 209.4–214.0 MiB. I imagine the boot time saving will be a lot more significant on lower-end devices, and the memory impact is a big win. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Deriving the master key from the rootkey (Argon2id, 64 MiB memlimit) is paid on every boot — twice, in fact: once inside
MapeoManagerand once increateMapServer. On low-end devices that is a visible boot-time and memory cost for a deterministic mapping that never changes. This caches the derived key natively next to the rootkey and passes both on the init frame, so steady-state boots run no Argon2id at all. Full design, failure model, and rollout: docs/master-key-cache-plan.md (included in this PR).On a cache miss, Kotlin/Swift derive the key by
dlopen/dlsymof the sodium-native prebuild already shipped for the Node runtime (digidem/sodium-native-nodejs-mobile#3 adds the exportedsnm_*wrappers), so native and Node derivation agree by construction. The cache is written and read-back-verified before Node boots — no new IPC frames; the only protocol change is the optionalmasterKeyfield on the existing init frame. The stores treat it as a pure cache: any failure (corrupt envelope, fingerprint mismatch against the rootkey, missing symbols, even the derivation shim failing to load) deletes the entry or degrades to derivation, never blocking boot and never touching the rootkey. The backend keeps a derive-if-absent fallback whoseboot.master-key-derivespan is the telemetry signal for a degraded device. The master key is scrubbed everywhere the rootkey is (Sentry scrub layers + tripwire, including quoted/hyphenated/prefixed-identifier shapes).Reviewed by a three-way agent pass; findings addressed include an FGS crash path when the derivation shim can't load (now degrades to a rootkey-only init), tests that pin the pass-through and derivation count (mutation-checked), keypair validation in
createMapServer, a canonical-base64 round-trip check on init keys, and alignment with the merged upstream API (@comapeo/crypto,getMasterKey()).Verified: backend 127 tests, root jest 89, Android JVM 158, Android on-device storage matrix 19/19 (Pixel 7a API 34), iOS Swift package 163 — all green; lint/tsc clean. The on-device derive contract tests fail by design against today's prebuilds (verified failing at exactly the missing-
snm_*step, which also exercises the fallback) and go green once the patched prebuild release is dispatched.Merge sequencing: needs
@comapeo/[email protected](renamed upstream; masterKey support merged in digidem/comapeo-crypto#37) and@comapeo/[email protected](digidem/comapeo-core#1310) published, then onenpm install --prefix backendto regenerate the lockfile (deliberately not regenerated here — the pinned versions are unpublished, so backend CI fails until then), plus the refreshed sodium-native 5.1.0 prebuild release.