Repository navigation
Reuse validated cryptographic facts during message and sigchain processing - #39
Conversation
Import immutable keysets into a private Team-owned store and retain successful delivery bindings across replay. Select keys only through the current state, keeping cryptographic material separate from authorization. Replace the global keyset, lockbox-opening, and key-map caches while preserving standalone validation and caller-owned open results. Validate with 765 passing auth, CRDX, crypto, and shared tests (87 existing skips), production builds, scoped lint, and separate-sender forced-GC edition checks at 10 and 100 users. The test-inclusive auth typecheck has 37 existing diagnostics versus 39 at the baseline, with no new diagnostics. Assisted-by: Codex
Discard the Team-owned checked-key store when decryption or merge validation fails, preventing rejected graph prefixes from retaining speculative keys for the Team lifetime. Preserve reuse after successful merges. Add realistic repeated-rejection regressions for semantic and ciphertext failures, followed by acceptance and reuse of the valid prefix. Both regressions failed before the fix and pass afterward. Validation: 767 tests passed with 87 existing skips, auth production build and scoped lint passed, and the broad test-inclusive typecheck has the same 37 pre-existing diagnostics. Assisted-by: Codex
Resolve packages/auth/src/team/selectors/keys.ts: keep the per-team checked-key store threading from this branch and main's redacted missing-key diagnostics (#35). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ce keys owned after a rejected merge Add checkedKeyProperties.test.ts covering, on real Team graphs: retained keys are not selectable from a branch that never delivered them; a cached opening cannot serve a different recipient or a re-addressed delivery; a rejected merge leaves nothing selectable from its accepted prefix; no retained secret reaches save() or state; repeated graph replays reuse one record per delivery. Team.merge re-imports the team's own lockbox keys into the fresh store after a rejected merge, so later key use does not re-run keypair validation on every call. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Landing review (merge onto main + security properties)Merge: Tests (local, Node 24,
No pre-existing or new failures. Five properties, with evidence:
Not a breaking change: public Team/selector signatures gain only optional trailing |
… key store Daybreak Blue audit M-1: CheckedKeyStore.import() strongly retained every distinct valid caller-supplied keyset for the Team's lifetime, so explicit key lookups with unrelated keysets grew the store without bound. Ownership is now a WeakMap; only pin() (the Team's own lockbox keys) and successful delivery contents enter the strong material map. The single selection view is keyed on the recipient commitment, so repeated lookups with the same explicit keys still reuse it. Regression tests force GC and check transient imports are collectable while pinned material stays owned. Also correct docs/checked-key-material.md (audit I-1): the graph signature/decryption/proof caches and the commitment trie are part of this change; describe their bindings, owners and caps. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Daybreak Blue adversarial audit — iteration 1: REJECT (fixed in 277792a)Independent audit of
Suite after fix: 816 passed / 87 skipped. Iteration 2 re-audit running on 277792a. |
Quiet revalidated the same lockbox key material for every message and repeated old graph cryptography when receiving a new sigchain edition. This change retains checked keys within each Team and reuses successful graph cryptographic facts for complete unchanged inputs. Ordinary message signatures and current action authorization are still checked.
Implementation
Checked-key records last for the owning Team's lifetime; they are not serialized. A failed merge discards the store so valid prefixes of rejected graphs cannot accumulate retained keys; successful merges keep their records. Existing Team APIs and wire formats are unchanged. Standalone lockbox opening returns caller-owned key material. See the checked-key design notes.
Validation
Graph traversal, hashing, filtering, and contextual replay remain proportional to history. Earlier integrated iPhone timings included a separate crypto adapter and are not performance measurements of this PR alone.
Integration
This PR changes auth only. Quiet needs a submodule pointer update to consume the latest commit; its channel index is separate. No native crypto implementation is included or required. The OpenSSL alternative is isolated in TryQuiet/quiet#3541, while native libsodium is being developed separately.
Part of TryQuiet/quiet#3536 and TryQuiet/quiet#3537; intended for TryQuiet/quiet#3539. Targets
release/10.0.0.