Repository navigation
Generic per-identity encryption trust, with OpenPGP multi-key Stage 2 built on it #1452
Description
Move OpenPGP multi-key trust onto a generic per-identity trust API shared with OMEMO, and do the trust-state migration once.
Context
#1115 teaches OpenPGP that a contact owns a set of announced keys (XEP-0374 §2.3.1: all keys MUST be used): encryption fans out to every active key, verification accepts any eligible key, and an incomplete keyset fails closed. Its planned "Stage 2" (verified key sets, set-mode verification dialog, verification-sync set format, trust-seal migration) exists only in its design spec, and as written it would store trust sets in app stores. Moving that state into plugin storage for the generic API later would then need a second migration of security-sensitive persisted trust.
Until this issue lands, #1115 ships with a derived "unverified keyset" signal: a verified contact who gains an active key that is not verified no longer shows the verified shield. That signal is computed on the fly and persists nothing, so it is safe to replace here.
Goal
A generic end-to-end encryption trust model in the SDK where a peer has N identities, each with its own trust, and where OpenPGP keys and OMEMO devices are both identities. OpenPGP implements it on #1115's keyset, which delivers #1115's Stage 2 in one migration.
Scope
- SDK API:
PeerIdentity,listPeerIdentities,setIdentityTrust, and a generic conversation-encryption state hook replacing the OpenPGP-specific plugin casts in the app. Thefeatures/omemobranch has a starting design, but it assumed one OpenPGP key per peer and must be redesigned for identity sets. - Plugin-owned verified state in per-plugin storage, not app stores.
- OpenPGP: per-key verification, a set format for verification sync, the trust-seal migration done once, and migration from today's single verified fingerprint per contact.
- Replace the derived "unverified keyset" signal from fix(e2ee): support multiple announced OpenPGP keys per account (#1059) #1115 with real per-identity trust states.
- Default trust for keys a contact announces over time follows blind trust before verification (BTBV), as used across the OMEMO ecosystem:
- Contact never verified: every valid announced key is trusted and used for encryption, as XEP-0374 §2.3.1 requires. Refusing a later key adds friction without security, since the first key was also accepted without verification.
- Contact verified at least once: a newly announced key is shown but not used for encryption until the user verifies or approves that key, and the reason is explained in the conversation. Auto-trusting it would defeat the earlier verification.
- Per-key approval is part of this issue. Until it lands, fix(e2ee): support multiple announced OpenPGP keys per account (#1059) #1115's derived signal only removes the verified state while still encrypting to every active key.
Dependencies
- fix(e2ee): support multiple announced OpenPGP keys per account (#1059) #1115 with its unverified-keyset signal.
- Generic encryption API groundwork: decoupling OpenPGP-specific code from the SDK encryption layer, and per-plugin storage.
Acceptance
- One persisted trust migration, with an explicit migration or fallback path for existing profiles.
- A verified contact gaining a new identity is surfaced per identity, never silently trusted under a verified state, and that identity is not used for encryption until approved.
- A never-verified contact's new identities are used for encryption without user action.
- OpenPGP behaviour for single-key contacts is unchanged.
- The same API is usable by an OMEMO plugin without OpenPGP-specific branches.
Activity
fix(e2ee): stop showing a verified contact with an unverified key as …
fix(e2ee): support multiple announced OpenPGP keys per account (#1059) (