#119 Add keyring-based group sharing

closed medium · sable · 2026-03-02 23:37 · closed 2026-03-02 23:37 · feature · Phase 3: Keyrings

Subtasks

Comments — 2

sable note 2026-03-02 23:37

Phase 3: Keyrings. Named groups with a shared symmetric group key (GK), wrapped to each member's DID pubkey. Documents encrypted under a keyring have their content key wrapped under GK instead of individual pubkeys. Adding a member = wrap GK to their pubkey. Removing a member = rotate GK, re-wrap to remaining members, increment rotation counter. Documents reference the rotation epoch they were encrypted under (keyringRef.rotation field added in lexicon defs).

sable note 2026-03-02 23:37

SESSION 8 PLAN (2026-03-01):

Keyrings are the Phase 3 feature. Architectural decisions confirmed:

CRYPTO MODEL:

  • Group key (GK) is a random AES-256 key, same as content keys
  • GK is wrapped to each member's X25519 public key using the same x25519-hkdf-a256kw algorithm as direct sharing
  • Documents under a keyring have their content key wrapped under GK (not individual pubkeys)
  • Two-layer key: rotate GK without re-encrypting every document blob — only re-wrap GK to remaining members
  • Rotation counter (u32) increments on each member removal. Documents reference the rotation epoch via keyringRef.rotation

RECORD TYPE (already in lexicon):

  • app.opake.cloud.keyring with fields: name, algo, members (array of wrappedKey), rotation, createdAt, modifiedAt
  • Keyring struct already exists in records.rs with Versioned impl

EXISTING CODE:

  • crypto.rs has create_group_key() and a failing should_panic test for keyring content key wrapping (#16 marker)
  • records.rs has Keyring struct, KeyringRef struct, KeyringEncryption variant in Encryption enum

SUBISSUES:

  • #17: keyring create — generate GK, wrap to self, create record
  • #18: keyring add-member — resolve DID, wrap GK to their pubkey, update record
  • #19: keyring remove-member — rotate GK, re-wrap to remaining members, increment rotation
  • #20: keyring ls — list keyrings (uses list_collection generic)
  • #21: upload --keyring — encrypt content key under GK instead of direct wrapping

SEQUENCING within this session: 1. Fix the failing crypto test — implement wrap_content_key_to_group_key / unwrap_content_key_from_group_key 2. #17 keyring create (core + CLI) 3. #20 keyring ls (core + CLI, trivial with list_collection) 4. #18 keyring add-member 5. #21 upload --keyring 6. #19 keyring remove-member with rotation (most complex)

Generated 2026-03-03 02:53 UTC