Merge pull request #15 from mrteye/feat-recovery-sss-matrix-task-4186155517714950179
Add task file for 2-of-3 SSS Wasm recovery matrix
This commit is contained in:
commit
792ed141d2
@ -0,0 +1,43 @@
|
|||||||
|
# TASK METADATA
|
||||||
|
|
||||||
|
- **Target Files:** `ui/components/RecoveryPage.tsx`, `server/main.ts`, `server/recovery.ts` (new), `wasm/sss_recovery/` (new Rust module)
|
||||||
|
- **Core Objective:** Implement constant-time 2-of-3 Shamir's Secret Sharing (SSS) key splitting and reconstruction in WebAssembly/Rust for the client-side zero-downgrade recovery portal, with mandatory in-place memory zeroization.
|
||||||
|
- **Dependencies:** Deno WebCrypto API, SimpleWebAuthn (client & server), Rust/Wasm toolchain (`wasm-pack`), IndexedDB.
|
||||||
|
- **Additional Important Notes:** Share choreography uses a Device Share (IndexedDB via WebAuthn PRF), Hot Server Share (PostgreSQL via PIN), and Cold Voucher (BIP-39 mnemonic). The execution sandbox must use Web Workers or strict in-memory client modules with mandatory `Uint8Array.fill(0)` zeroization; isolated iframes are rejected to prevent `postMessage` memory leakage.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architectural Considerations & Risks
|
||||||
|
|
||||||
|
- **Risks:**
|
||||||
|
- **Garbage Collection Leaks:** Transferring ArrayBuffers between JavaScript and Wasm can leave un-zeroed memory in V8. Strict lifecycle management and immediate `Uint8Array.fill(0)` on all JS-side buffers is mandatory before losing references.
|
||||||
|
- **Side-Channel Attacks:** Polynomial interpolation in Rust over GF(256) must be constant-time to avoid timing attacks when processing recovery shares.
|
||||||
|
- **WebAuthn PRF Extension Support:** The Device Share in IndexedDB relies on the WebAuthn PRF extension. A fallback or clear UX flow must be designed if the user's authenticator lacks PRF support.
|
||||||
|
- **Brute-Forcing Server Share:** The Hot Server Share is gated by a recovery PIN/code. Robust rate-limiting on the `/api/recovery/challenge` endpoint is critical to prevent brute-forcing the server share.
|
||||||
|
- **Alternatives:**
|
||||||
|
- **Execution Context:** We explicitly rejected using an isolated sandbox iframe. `postMessage` serializes data, creating uncontrollable memory copies in the DOM that cannot be deterministically zeroed. We will use a Web Worker or direct WebAssembly instantiation in the main thread with explicit TypedArray zeroization.
|
||||||
|
- **Implementation Language:** Pure TypeScript SSS was rejected due to lack of constant-time execution guarantees and poor low-level memory control compared to Rust/Wasm.
|
||||||
|
|
||||||
|
## Proposed Implementation
|
||||||
|
|
||||||
|
### Phase 1: Wasm Core Engine (Rust)
|
||||||
|
1. Scaffold a new Rust crate (e.g., `wasm/sss_recovery`) compiling to `wasm32-unknown-unknown`.
|
||||||
|
2. Implement a constant-time 2-of-3 Shamir's Secret Sharing reconstruction algorithm over GF(256).
|
||||||
|
3. Expose FFI boundaries that accept two share buffers and output the reconstructed master secret.
|
||||||
|
4. Utilize `zeroize` crate in Rust to ensure Wasm linear memory is purged of intermediate polynomial data before returning control to JavaScript.
|
||||||
|
|
||||||
|
### Phase 2: Client-Side Choreography (`ui/components/RecoveryPage.tsx`)
|
||||||
|
1. Implement the UI flow for the two recovery scenarios:
|
||||||
|
- **Scenario A (Lost Key):** Fetch Device Share (IndexedDB + WebAuthn PRF) + Server Share (via PIN).
|
||||||
|
- **Scenario B (Lost Device):** Prompt for Cold Voucher (12-word BIP-39) + Server Share (via PIN).
|
||||||
|
2. Instantiate the Wasm SSS module.
|
||||||
|
3. Pass the two gathered shares to the Wasm module to reconstruct the master secret.
|
||||||
|
4. Import the reconstructed master secret directly into WebCrypto as an `extractable: false` `CryptoKey`.
|
||||||
|
5. **Memory Purge:** Immediately execute `Uint8Array.fill(0)` on the share inputs, intermediate buffers, and the raw reconstructed byte array.
|
||||||
|
6. Use the WebCrypto key to derive the ephemeral recovery token and sign the challenge for the new passkey registration.
|
||||||
|
|
||||||
|
### Phase 3: Server-Side Share Gating (`server/main.ts`, `server/recovery.ts`)
|
||||||
|
1. Implement backend storage for the Hot Server Share within the `recovery_shares` table (or similar schema extension).
|
||||||
|
2. Update `/api/recovery/challenge` to validate the recovery PIN and release the Hot Server Share only upon success, enforcing strict rate-limiting.
|
||||||
|
3. Update `/api/recovery/verify` to validate the ephemeral token signature derived from the reconstructed master secret.
|
||||||
|
4. Complete the recovery cycle by binding the new WebAuthn passkey, revoking the old credentials, and generating a new 2-of-3 share matrix for the new passkey.
|
||||||
Loading…
x
Reference in New Issue
Block a user