From 224be5386711581f5047cb3c7c52c26a43ce40cb Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Mon, 3 Aug 2026 07:36:50 -0700 Subject: [PATCH] Convert password-to-cryptokey static class to module function. --- src/lib/vault/passkey.ts | 78 +++++++++++++++++------------------ src/lib/vault/vault-worker.ts | 4 +- 2 files changed, 40 insertions(+), 42 deletions(-) diff --git a/src/lib/vault/passkey.ts b/src/lib/vault/passkey.ts index 58ecba7..a3c5806 100644 --- a/src/lib/vault/passkey.ts +++ b/src/lib/vault/passkey.ts @@ -1,49 +1,47 @@ //! SPDX-FileCopyrightText: 2025 Chris Duncan //! SPDX-License-Identifier: GPL-3.0-or-later -export class Passkey { - static create (action: string, salt: ArrayBuffer, data: Record): Promise { - // Allowlisted wallet actions - if (['create', 'load', 'unlock', 'update'].includes(action)) { +export async function passkey (action: string, salt: ArrayBuffer, data: Record): Promise { + // Allowlisted wallet actions + if (['create', 'load', 'unlock', 'update'].includes(action)) { - // Create local copy of password ASAP, then clear bytes from original buffer - if (!(data.password instanceof ArrayBuffer)) { - throw new TypeError('Password must be ArrayBuffer') - } + // Create local copy of password ASAP, then clear bytes from original buffer + if (!(data.password instanceof ArrayBuffer)) { + throw new TypeError('Password must be ArrayBuffer') + } - const password = data.password.slice() - new Uint8Array(data.password).fill(0) - delete data.password + const password = data.password.slice() + new Uint8Array(data.password).fill(0) + delete data.password - // Only unlocking should decrypt the vault; other sensitive actions should - // throw if the vault is still locked and encrypted - const keyUsages: KeyUsage[] = action === 'unlock' ? ['decrypt'] : ['encrypt'] + // Only unlocking should decrypt the vault; other sensitive actions should + // throw if the vault is still locked and encrypted + const keyUsages: KeyUsage[] = action === 'unlock' ? ['decrypt'] : ['encrypt'] - return crypto.subtle - .importKey('raw', password, 'PBKDF2', false, ['deriveKey']) - .then(derivationKey => { - new Uint8Array(password).fill(0) - const derivationAlgorithm: Pbkdf2Params = { - name: 'PBKDF2', - hash: 'SHA-512', - iterations: 210000, - salt - } - const derivedKeyType: AesKeyGenParams = { - name: 'AES-GCM', - length: 256 - } - return crypto.subtle - .deriveKey(derivationAlgorithm, derivationKey, derivedKeyType, false, keyUsages) - }) - .catch(err => { - console.error(err) - throw new Error('Failed to derive CryptoKey from password', { cause: err }) - }) - } else if (data.password !== undefined) { - throw new Error('Password is not allowed for this action', { cause: action }) - } else { - return Promise.resolve(undefined) - } + return crypto.subtle + .importKey('raw', password, 'PBKDF2', false, ['deriveKey']) + .then(derivationKey => { + new Uint8Array(password).fill(0) + const derivationAlgorithm: Pbkdf2Params = { + name: 'PBKDF2', + hash: 'SHA-512', + iterations: 210000, + salt + } + const derivedKeyType: AesKeyGenParams = { + name: 'AES-GCM', + length: 256 + } + return crypto.subtle + .deriveKey(derivationAlgorithm, derivationKey, derivedKeyType, false, keyUsages) + }) + .catch(err => { + console.error(err) + throw new Error('Failed to derive CryptoKey from password', { cause: err }) + }) + } else if (data.password !== undefined) { + throw new Error('Password is not allowed for this action', { cause: action }) + } else { + return Promise.resolve(undefined) } } diff --git a/src/lib/vault/vault-worker.ts b/src/lib/vault/vault-worker.ts index 57c73b8..c23c67f 100644 --- a/src/lib/vault/vault-worker.ts +++ b/src/lib/vault/vault-worker.ts @@ -10,7 +10,7 @@ import { dec, utf8 } from '../convert' import { Bip39, Bip44, Blake2b, WalletAesGcm } from '../crypto' import { WalletType } from '../wallet' import { parseAction, parseData, parseId, parseIv, parseKeySalt, parseType } from './parsers' -import { Passkey } from './passkey' +import { passkey } from './passkey' import { VaultTimer } from './vault-timer' let _locked: boolean = true @@ -37,7 +37,7 @@ const listener = (event: MessageEvent): void => { NODE: if (parentPort == null) setTimeout(() => listener(event), 0) const action = parseAction(data) const keySalt = parseKeySalt(action, data) - Passkey.create(action, keySalt, data) + passkey(action, keySalt, data) .then((key: CryptoKey | undefined): Promise | void> => { const type = parseType(action, data) const id = parseId(action, data) -- 2.52.0