Skip to content

Social recovery UI with guardian threshold #157

Description

@truthixify

Tier: L (5-7 days) | Type: feature + security

Context. Passkey and recovery-kit both fail if the user loses the device before backing up. Social recovery covers the last-mile: nominate N guardians, require M shares to hand a fresh browser session the viewing scalar. Recovery happens client-side; guardians only ever see shares.

Revised after review. The original acceptance list contained two criteria that are not achievable as written. Both are corrected below, and the corrected behaviour is the requirement.

  1. Rotation revokes shares, not capability. The viewing scalar is sha256("wraith:viewing:" || signature) over a fixed signing message (sdk/src/chains/stellar/keys.ts), so it is deterministic and does not change. Re-sharing with a new polynomial invalidates old shares, but any M guardians who colluded before rotation retain the scalar permanently, for past and future deposits alike. A control labelled "Revoke" that does not revoke access is worse than no control. Deriving a fresh scalar requires a new domain-separated signing message, which yields a different meta-address, and funds already sent to the old address stay scannable with the old scalar forever. That migration is out of scope here.
  2. Plain Shamir has no integrity. Handed a wrong or mismatched share, SSS does not fail, it silently reconstructs a different scalar and the page "succeeds" into an empty vault. "Fewer than M refuses to reconstruct" is therefore only satisfiable with an explicit commitment.

Scope.

  • Guardian setup wizard using Shamir secret sharing over the viewing scalar (N of M configurable, default 3 of 5).
  • Commit a hash of the scalar alongside the share set and verify after reconstruction; per-share checksums so a bad share can be named rather than failing anonymously.
  • Embed threshold and a share-set id in share metadata and check both, so old shares are rejected deterministically rather than by chance.
  • Each guardian receives a URL fragment carrying one share. Encrypt each share under a short code delivered over a second channel, and strip the fragment with history.replaceState on load so it does not persist in history.
  • Recovery page collects shares and reconstructs the scalar client-side.
  • Guardian management: re-share to a new guardian set, view current threshold.
  • In-page trust-model callout stating plainly what rotation does and does not achieve, per point 1 above.

Acceptance.

  • Round-trip: setup 3-of-5, recover with 3 shares on a fresh browser
  • Fewer than M shares, or any mismatched share, is detected and reported rather than silently reconstructing a wrong scalar (commitment check)
  • A bad share is identified individually by its checksum
  • Re-sharing rejects shares from a previous share-set id
  • Trust-model callout states that re-sharing revokes shares but not prior capability
  • Contributor recording of the full flow, using throwaway values only, never real shares

Files. src/pages/Recovery.tsx (new), src/lib/stellar/socialRecovery.ts (new), src/pages/Settings.tsx, src/vault/KeyVault.ts.

Metadata

Metadata

Assignees

Labels

Stellar WaveIssues in the Stellar wave programdemoAuto-created for Wave 8dripsFunded via Drips NetworkfeatureNew feature workhelp wantedExtra attention is neededsecuritySecurity-sensitive workstellarTouches Stellar / Soroban codestellar-waveAuto-created for Wave 8wave-8Auto-created for Wave 8

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions