UNPKG

@bsv/wallet-toolbox

Version:

BRC100 conforming wallet, wallet storage and wallet signer components

213 lines 7.69 kB
/** * ShamirWalletManager * * A wallet manager that uses Shamir Secret Sharing for key recovery * instead of password-derived keys and on-chain UMP tokens. * * Security improvements over CWIStyleWalletManager: * - No password enumeration attacks possible (no password-derived keys) * - No encrypted key material stored on-chain * - Server only holds 1 share (cannot reconstruct alone) * - Defense-in-depth with mouse entropy + CSPRNG for key generation * * Default configuration (2-of-3): * - Share 1 (server): Stored on WAB server, released only after OTP verification * - Shares 2..n (user): Application decides how to store (print, password manager, etc.) * * The threshold and total shares are configurable. WAB always stores exactly one share. */ import { PrivateKey, WalletInterface } from '@bsv/sdk'; import { PrivilegedKeyManager } from './sdk/PrivilegedKeyManager'; import { EntropyProgressCallback } from './entropy/EntropyCollector'; /** * Result from creating a new Shamir-based wallet */ export interface CreateShamirWalletResult { /** * User shares to be stored by the application (excludes server share) * For 2-of-3: returns 2 shares, server holds 1 * For 3-of-5: returns 4 shares, server holds 1 */ userShares: string[]; /** Hash of the user's identity key (used for server lookup) */ userIdHash: string; /** The generated private key (for immediate wallet use) */ privateKey: PrivateKey; /** The threshold used (k shares needed to reconstruct) */ threshold: number; /** Total number of shares generated */ totalShares: number; } /** * Configuration for ShamirWalletManager */ export interface ShamirWalletManagerConfig { /** WAB server URL */ wabServerUrl: string; /** Auth method type for OTP verification (e.g., "TwilioPhone") */ authMethodType: string; /** Function to build the underlying wallet from a private key */ walletBuilder: (privateKey: PrivateKey, privilegedKeyManager: PrivilegedKeyManager) => Promise<WalletInterface>; /** * Number of shares required to reconstruct the key (default: 2) * Must be >= 2 and <= totalShares */ threshold?: number; /** * Total number of shares to generate (default: 3) * WAB server stores 1, application receives (totalShares - 1) */ totalShares?: number; } /** * Callback for handling user shares during wallet creation */ export type ShareStorageCallback = (shares: string[], threshold: number, totalShares: number) => Promise<boolean>; export declare class ShamirWalletManager { private config; private wabClient; private entropyCollector; private privateKey?; private underlying?; private userIdHash?; private readonly threshold; private readonly totalShares; constructor(config: ShamirWalletManagerConfig); /** * Get the configured threshold */ getThreshold(): number; /** * Get the configured total shares */ getTotalShares(): number; /** * Reset the entropy collector (e.g., if user wants to start over) */ resetEntropy(): void; /** * Add a mouse movement sample for entropy collection * Call this from your UI's mousemove handler */ addMouseEntropy(x: number, y: number): import("./entropy/EntropyCollector").EntropyProgress | null; /** * Check if enough entropy has been collected */ hasEnoughEntropy(): boolean; /** * Get entropy collection progress */ getEntropyProgress(): import("./entropy/EntropyCollector").EntropyProgress; /** * Collect entropy from browser mouse movements * Convenience method that sets up event listeners automatically */ collectEntropyFromBrowser(element?: EventTarget, onProgress?: EntropyProgressCallback): Promise<void>; /** * Generate a user ID hash from a private key * This is used to identify the user on the WAB server without revealing the key */ private generateUserIdHash; /** * Create a new wallet with Shamir key split * * Flow: * 1. Generate private key from entropy * 2. Split into Shamir shares (threshold-of-totalShares) * 3. Store first share on WAB server (requires OTP verification) * 4. Return remaining shares for application to handle * * @param authPayload Auth method specific payload (e.g., { phoneNumber: "+1...", otp: "123456" }) * @param onUserSharesReady Callback when user shares are ready - return true to confirm saved * @returns Result containing user shares (server share already stored) */ createNewWallet(authPayload: { phoneNumber?: string; email?: string; otp: string; }, onUserSharesReady: ShareStorageCallback): Promise<CreateShamirWalletResult>; /** * Start OTP verification for share retrieval * Call this before recoverWithSharesBC */ startOTPVerification(payload: { phoneNumber?: string; email?: string; }): Promise<void>; /** * Set the user ID hash for recovery operations * This can be computed from Share A or C (both contain the same threshold/integrity) */ setUserIdHash(userIdHash: string): void; /** * Recover wallet using user shares plus the server share * Requires OTP verification to retrieve the server share * * @param userShares Array of user-held shares (need threshold-1 shares) * @param authPayload Contains OTP code and auth method data */ recoverWithServerShare(userShares: string[], authPayload: { phoneNumber?: string; email?: string; otp: string; }): Promise<PrivateKey>; /** * Recover wallet using only user-held shares (no server interaction) * Requires at least threshold shares * * @param userShares Array of user-held shares (need at least threshold shares) */ recoverWithUserShares(userShares: string[]): Promise<PrivateKey>; /** * Extract threshold from a share (format: x.y.threshold.integrity) */ private getThresholdFromShare; /** * Build the underlying wallet after key recovery */ buildWallet(): Promise<WalletInterface>; /** * Get the underlying wallet (must call buildWallet first) */ getWallet(): WalletInterface; /** * Rotate keys - generate new key and update server share * User must save new user shares * * @param authPayload Contains OTP code and auth method data * @param onUserSharesReady Callback when new user shares are ready */ rotateKeys(authPayload: { phoneNumber?: string; email?: string; otp: string; }, onUserSharesReady: ShareStorageCallback): Promise<CreateShamirWalletResult>; /** * Validate Shamir share format * Expected format: x.y.threshold.integrity (4 dot-separated parts) */ private validateShareFormat; /** * Check if the manager has a loaded private key */ hasPrivateKey(): boolean; /** * Get the user ID hash (for display or storage) */ getUserIdHash(): string | undefined; /** * Delete the user's account and stored share from the WAB server * Requires OTP verification * * WARNING: This permanently deletes the server share. * User must have enough remaining shares to meet the threshold for recovery. * * @param authPayload Contains OTP code and auth method data */ deleteAccount(authPayload: { phoneNumber?: string; email?: string; otp: string; }): Promise<void>; } //# sourceMappingURL=ShamirWalletManager.d.ts.map