From: Chris Duncan Date: Mon, 3 Aug 2026 14:38:41 +0000 (-0700) Subject: Enforce strong wallet passwords. X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=d3cb478ef8c9c0c29dafd119632c8d3393b619c1;p=libnemo.git Enforce strong wallet passwords. --- diff --git a/src/lib/wallet/create.ts b/src/lib/wallet/create.ts index d9d2376..cf6fb52 100644 --- a/src/lib/wallet/create.ts +++ b/src/lib/wallet/create.ts @@ -19,9 +19,7 @@ export async function _create (wallet: Wallet, vault: Vault, password: unknown, encrypted: new ArrayBuffer(0) } if (wallet.type !== 'Ledger') { - if (typeof password !== 'string') { - throw new TypeError('Password must be a string') - } + Wallet.zxcvbn(password) if (mnemonicSalt !== undefined && typeof mnemonicSalt !== 'string') { throw new TypeError('Mnemonic salt must be a string') } diff --git a/src/lib/wallet/index.ts b/src/lib/wallet/index.ts index 9579d4a..bc0bb80 100644 --- a/src/lib/wallet/index.ts +++ b/src/lib/wallet/index.ts @@ -1,6 +1,9 @@ //! SPDX-FileCopyrightText: 2025 Chris Duncan //! SPDX-License-Identifier: GPL-3.0-or-later +import { ZxcvbnFactory } from '@zxcvbn-ts/core' +import * as zxcvbnCommonPackage from '@zxcvbn-ts/language-common' +import * as zxcvbnEnPackage from '@zxcvbn-ts/language-en' import { UUID } from 'crypto' import { Account } from '../account' import { Block } from '../block' @@ -33,6 +36,23 @@ export type WalletType = 'BIP-44' | 'BLAKE2b' | 'Exodus' | 'Ledger' */ export class Wallet { static #isInternal: boolean = false + static #zxcvbn: ZxcvbnFactory = new ZxcvbnFactory({ + translations: zxcvbnEnPackage.translations, + graphs: zxcvbnCommonPackage.adjacencyGraphs, + dictionary: { + ...zxcvbnCommonPackage.dictionary, + ...zxcvbnEnPackage.dictionary, + } + }) + static zxcvbn (password: unknown): asserts password is string { + if (typeof password !== 'string') { + throw new TypeError('Password must be a string') + } + const passwordCheck = this.#zxcvbn.check(password) + if (passwordCheck.score < 4) { + throw new RangeError('Weak password', { cause: passwordCheck }) + } + } /** * @returns {boolean} diff --git a/src/lib/wallet/load.ts b/src/lib/wallet/load.ts index bedb522..49bac76 100644 --- a/src/lib/wallet/load.ts +++ b/src/lib/wallet/load.ts @@ -23,12 +23,10 @@ export async function _load (wallet: Wallet, vault: Vault, password: unknown, se throw new Error('Failed to initialize Ledger wallet', { cause: 'Browser is unsupported' }) } } else { + Wallet.zxcvbn(password) if (wallet.type !== 'BIP-44' && wallet.type !== 'BLAKE2b' && wallet.type !== 'Exodus') { throw new TypeError('Invalid wallet type', { cause: wallet.type }) } - if (typeof password !== 'string') { - throw new TypeError('Password must be a string') - } if (typeof secret !== 'string') { throw new TypeError('Wallet secret must be a string') } diff --git a/src/lib/wallet/update.ts b/src/lib/wallet/update.ts index fb9e33f..9ed6dfd 100644 --- a/src/lib/wallet/update.ts +++ b/src/lib/wallet/update.ts @@ -10,9 +10,7 @@ export async function _update (wallet: Wallet, vault: Vault, password?: string): export async function _update (wallet: Wallet, vault: Vault, password: unknown): Promise { try { if (wallet.type !== 'Ledger') { - if (typeof password !== 'string') { - throw new TypeError('Password must be a string') - } + Wallet.zxcvbn(password) const pending = vault.request({ action: 'update', password: utf8.toBuffer(password)