From 6a78f8fefe71e636c847e1402b08b1d60483565b Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Mon, 17 Aug 2026 11:16:25 -0700 Subject: Own entropy means owned outcome: the typed text alone derives the seed, so re-typing it is an import on any device — the warn-box says what that guarantee costs, and Regenerate bows out of a deterministic job MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01JtaatFfAbx91Nh3xqKVqKz --- src/wallet.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'src/wallet.js') diff --git a/src/wallet.js b/src/wallet.js index 2ede69d..cdae1ff 100644 --- a/src/wallet.js +++ b/src/wallet.js @@ -66,14 +66,13 @@ export const NETS = { export function newMnemonic(strengthBits = 128, extraEntropy = '') { if (!extraEntropy) return generateMnemonic(wordlist, strengthBits); - // User entropy is MIXED with the CSPRNG, never used alone: hashing the two - // together can only add randomness — weak dice can't weaken the seed, and - // a distrusted device RNG can't fully determine it either. - const txt = new TextEncoder().encode(extraEntropy); - const rnd = crypto.getRandomValues(new Uint8Array(strengthBits / 8)); - const mix = new Uint8Array(txt.length + rnd.length); - mix.set(txt); mix.set(rnd, txt.length); - return entropyToMnemonic(sha256(mix).slice(0, strengthBits / 8), wordlist); + // User entropy is used ALONE, deterministically: seed = BIP-39 from + // SHA-256 of exactly the typed text. The same text recreates the same + // wallet on any device (that's the point — it doubles as an import), and + // the derivation is simple enough to verify elsewhere. The flip side — + // guessable text is stealable money — is the UI's warning to give. + const digest = sha256(new TextEncoder().encode(extraEntropy)); + return entropyToMnemonic(digest.slice(0, strengthBits / 8), wordlist); } // The base localStorage cache key for a wallet identity (xpub, xprv, or -- cgit v1.2.3