From: Chris Duncan Date: Tue, 9 Sep 2025 21:48:50 +0000 (-0700) Subject: Draft vault config. X-Git-Tag: v0.10.5~22^2~5 X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=7bd7847423c4a607934f8040cab590f6be2ab1ba;p=libnemo.git Draft vault config. --- diff --git a/src/lib/vault/vault-worker.ts b/src/lib/vault/vault-worker.ts index fb837d7..42f84fa 100644 --- a/src/lib/vault/vault-worker.ts +++ b/src/lib/vault/vault-worker.ts @@ -13,7 +13,8 @@ import { VaultTimer } from './vault-timer' export class VaultWorker { #encoder: TextEncoder = new TextEncoder() #locked: boolean - #timeout: VaultTimer + #timeout: number + #timer: VaultTimer #type?: 'BIP-44' | 'BLAKE2b' #seed?: ArrayBuffer #mnemonic?: ArrayBuffer @@ -21,7 +22,8 @@ export class VaultWorker { constructor () { this.#locked = true - this.#timeout = new VaultTimer(() => { }, 0) + this.#timeout = 120_000 + this.#timer = new VaultTimer(() => { }, 0) this.#type = undefined this.#seed = undefined this.#mnemonic = undefined @@ -30,6 +32,7 @@ export class VaultWorker { NODE: if (this.#parentPort == null) setTimeout(() => listener(event), 0) const data = this.#parseData(event.data) const action = this.#parseAction(data) + const config = this.#parseConfig(action, data) const keySalt = this.#parseKeySalt(action, data) Passkey.create(action, keySalt, data) .then((key: CryptoKey | undefined): Promise => { @@ -41,6 +44,9 @@ export class VaultWorker { BROWSER: close() NODE: process.exit() } + case 'config': { + return this.config(config) + } case 'create': { return this.create(type, key, keySalt, mnemonicSalt) } @@ -107,6 +113,17 @@ export class VaultWorker { } } + /** + * Configures vault settings. The wallet must be unlocked prior to + * configuration. + */ + config (config: { [key: string]: unknown }): Promise { + if (typeof config.timeout === 'number') { + this.#timeout = config.timeout + } + return Promise.resolve() + } + /** * Generates a new mnemonic and seed and then returns the initialization vector * vector, salt, and encrypted data representing the wallet in a locked state. @@ -141,7 +158,7 @@ export class VaultWorker { */ derive (index?: number): Promise> { try { - this.#timeout.pause() + this.#timer.pause() if (this.#locked) { throw new Error('Wallet is locked') } @@ -159,12 +176,12 @@ export class VaultWorker { : Blake2b.ckd(this.#seed, index) return derive.then(prv => { const pub = NanoNaCl.convert(new Uint8Array(prv)) - this.#timeout = new VaultTimer(() => this.lock(), 120000) + this.#timer = new VaultTimer(() => this.lock(), 120000) return { index, publicKey: pub.buffer } }) } catch (err) { console.error(err) - this.#timeout.resume() + this.#timer.resume() throw new Error('Failed to derive account', { cause: err }) } } @@ -195,7 +212,7 @@ export class VaultWorker { this.#mnemonic = undefined this.#seed = undefined this.#locked = true - this.#timeout?.pause() + this.#timer?.pause() BROWSER: postMessage('locked') NODE: this.#parentPort?.postMessage('locked') return Promise.resolve() @@ -207,7 +224,7 @@ export class VaultWorker { */ sign (index?: number, data?: ArrayBuffer): Promise> { try { - this.#timeout.pause() + this.#timer.pause() if (this.#locked) { throw new Error('Wallet is locked') } @@ -225,12 +242,12 @@ export class VaultWorker { : Blake2b.ckd(this.#seed, index) return derive.then(prv => { const sig = NanoNaCl.detached(new Uint8Array(data), new Uint8Array(prv)) - this.#timeout = new VaultTimer(() => this.lock(), 120000) + this.#timer = new VaultTimer(() => this.lock(), 120000) return { signature: sig.buffer } }) } catch (err) { console.error(err) - this.#timeout.resume() + this.#timer.resume() throw new Error('Failed to sign message', { cause: err }) } } @@ -257,7 +274,7 @@ export class VaultWorker { if (encrypted == null) { throw new TypeError('Wallet encrypted data is required') } - this.#timeout?.pause() + this.#timer?.pause() return WalletAesGcm.decrypt(type, key, iv, encrypted) .then(({ mnemonic, seed }) => { if (!(seed instanceof ArrayBuffer)) { @@ -269,13 +286,13 @@ export class VaultWorker { this.#seed = seed this.#mnemonic = mnemonic this.#locked = false - this.#timeout = new VaultTimer(this.lock.bind(this), 120000) + this.#timer = new VaultTimer(this.lock.bind(this), 120000) BROWSER: postMessage('unlocked') NODE: this.#parentPort?.postMessage('unlocked') }) .catch(err => { console.error(err) - this.#timeout?.resume() + this.#timer?.resume() throw new Error('Failed to unlock wallet', { cause: err }) }) } @@ -285,7 +302,7 @@ export class VaultWorker { */ update (key?: CryptoKey, salt?: ArrayBuffer): Promise> { try { - this.#timeout.pause() + this.#timer.pause() if (this.#locked) { throw new Error('Wallet is locked') } @@ -300,12 +317,12 @@ export class VaultWorker { } return WalletAesGcm.encrypt(this.#type, key, this.#seed, this.#mnemonic) .then(({ iv, encrypted }) => { - this.#timeout = new VaultTimer(() => this.lock(), 120000) + this.#timer = new VaultTimer(() => this.lock(), 120000) return { iv, salt, encrypted } }) } catch (err) { console.error(err) - this.#timeout.resume() + this.#timer.resume() throw new Error('Failed to update wallet password', { cause: err }) } } @@ -512,6 +529,7 @@ export class VaultWorker { throw new TypeError('Wallet action is required') } if (data.action !== 'STOP' + && data.action !== 'config' && data.action !== 'create' && data.action !== 'derive' && data.action !== 'load' @@ -525,6 +543,17 @@ export class VaultWorker { return data.action } + // Action for configuring vault + #parseConfig (action: string, data: { [key: string]: unknown }) { + const config: any = {} + if (action === 'config') { + if (data.timeout != null) { + config.timeout = data.timeout + } + } + return config + } + // Worker message data itself #parseData (data: unknown) { if (data == null) {