返回文章列表

Web3 浏览器钱包:助记词、私钥存储与用户密码

·6 分钟阅读·#Web3#钱包#助记词#私钥
目录 (9)

Web3 浏览器钱包:助记词、私钥存储与用户密码

最近开始接触 Web3,在做浏览器钱包插件开发时会频繁遇到助记词私钥Keystore钱包密码这几个概念:助记词是怎么来的?私钥存在哪里、怎么加密?用户设的那个「密码」到底管什么用?本文结合主流标准(BIP-39、BIP-32、Web3 Secret Storage)做个简要梳理,并配一些插件里常用的代码示例,方便在开发浏览器钱包扩展时理解与实现。

开发中常用依赖示例(下文代码基于此类库):

// 助记词与 HD 派生:bip39 + ethers 或 @ethersproject/hdnode
import { ethers } from "ethers";
// 或
import * as bip39 from "bip39";
import { HDNodeWallet } from "ethers";

一、助记词是怎么生成的

助记词(Mnemonic),在不少钱包里也叫「Secret Recovery Phrase / 恢复短语」,是一串由 12 或 24 个英文单词组成的句子,用来备份和恢复整个钱包:有了助记词,可以在任意兼容的钱包里重新导出所有派生出的私钥和地址。其生成和还原遵循 BIP-39 标准。

1. 生成流程(助记词从哪来)

  • 第一步:生成熵(Entropy)
    先产生一段完全随机的二进制数据「熵」,长度必须是 32 的倍数,常见为 128 位或 256 位:

    • 128 位熵 → 对应 12 个助记词
    • 256 位熵 → 对应 24 个助记词
      熵必须来自密码学安全的随机源(CSPRNG),不能是可预测的。
  • 第二步:加校验和
    对熵做 SHA-256,取哈希的前若干位(位数 = 熵长度 / 32)作为校验和,拼在熵的后面。这样在用户日后输入助记词时,可以校验是否输错或漏词。

  • 第三步:按 11 位切块 → 映射到词库
    把「熵 + 校验和」按每 11 位切成多段,每段对应 0~2047 的一个数,再映射到 BIP-39 规定的 2048 个英文单词 词库里的某一个词(11 位二进制刚好 2^11=2048 种取值)。

  • 第四步:得到助记词
    把这些词用空格连起来,就是最终的助记词。12 词约对应 128 位熵,组合空间约 2^128 量级(约 3.4×10^38),暴力破解不现实;24 词则更大。

助记词本质上是「随机熵 + 校验」的人眼可读编码,不是密码学意义上的「密钥」,但谁拿到助记词谁就能在兼容钱包里恢复出同一套私钥,所以必须当作最高等级机密保管。

插件里生成与校验助记词(示例)

import * as bip39 from "bip39";

// 生成 12 词助记词(128 位熵)
const mnemonic12 = bip39.generateMnemonic(128);

// 生成 24 词助记词(256 位熵)
const mnemonic24 = bip39.generateMnemonic(256);

// 校验用户输入的助记词是否合法(含校验和)
const isValid = bip39.validateMnemonic(userInputMnemonic);

二、从助记词到私钥:种子与派生

助记词本身不直接当私钥用,而是先转成「种子」,再按 BIP-32(HD 钱包) 从种子派生出无数个私钥和地址。

  • 助记词 → 种子(Seed)
    PBKDF2(HMAC-SHA512,迭代 2048 次):以可选的用户 passphrase 为密钥,以字符串 "mnemonic" + 助记词为盐,生成 512 位(64 字节)的种子。这个过程是单向的:有助记词可以算种子,有种子推不回助记词。若创建钱包时额外设了「扩展 passphrase」(俗称第 13/25 个词),它也会参与生成种子,忘记则无法恢复。

  • 种子 → 主私钥与派生路径
    种子通过 BIP-32 规定的层级推导,得到主私钥(master key),再按路径(如 m/44'/60'/0'/0/0 用于以太坊第一个账户)派生出每个账户的私钥和公钥。所以一个助记词对应一棵密钥树,所有「账户 1、账户 2、…」都是这棵树上不同路径的叶子,备份助记词就等于备份了整棵树。

助记词 → 种子 → 以太坊账户(ethers 示例)

import { ethers } from "ethers";

const mnemonic = "abandon abandon abandon ..."; // 12 或 24 词

// 从助记词创建 HD 钱包,默认路径 m/44'/60'/0'/0/0
const hdNode = ethers.HDNodeWallet.fromPhrase(mnemonic);

console.log(hdNode.privateKey); // 0x...
console.log(hdNode.address); // 0x...

// 派生第 N 个账户:m/44'/60'/0'/0/N
const account1 = ethers.HDNodeWallet.fromPhrase(
  mnemonic,
  undefined,
  `m/44'/60'/0'/0/1`,
);

三、私钥的存储机制

钱包里真正用来签名交易的是私钥。私钥在设备上的存在形式大致有几类:

1. 由助记词在内存中派生

创建/导入钱包时,用户输入助记词(和可选 passphrase),钱包在内存中算出种子并派生私钥,用于签名。助记词和原始私钥最好不要在磁盘上明文存储,否则一旦被恶意扩展或恶意软件读到,资产就会丢。

2. Keystore(加密后的私钥文件)

很多钱包(尤其是桌面端、早期以太坊钱包)会以 Keystore 形式存私钥:把私钥用用户密码派生的密钥加密后,存成 JSON 文件(Web3 Secret Storage 定义)。典型流程是:

  • KDF(如 scrypt 或 PBKDF2)从用户密码推导出加密密钥;
  • AES-128-CTR 等对称加密算法加密私钥;
  • MAC(如对密文做 Keccak-256)保证完整性,防止篡改。

使用时必须输入正确的用户密码才能解密出私钥。Keystore 和用户密码 两者缺一不可,丢了密码又没有助记词或私钥备份,就没办法恢复。

3. 浏览器扩展钱包的存储

浏览器插件钱包会把加密后的数据(助记词或派生出的密钥材料)存在扩展的本地存储里(例如 Chrome 的 Local Extension Storage),有的实现里把这段加密存储称为 vault(即「保险库」,比喻只能靠密码打开的密文数据):内容用**用户设置的「钱包密码」**加密后写入,只有在本机输入密码后才能解密到内存里用。也就是说:

  • 助记词 / 种子 在磁盘或扩展存储里是密文,解密密钥来自用户密码;
  • 用户密码不参与 BIP-39 的「助记词 → 种子」推导(那一层用的是可选的 passphrase),只负责本地加密存储,防止别人打开你浏览器就能直接用钱包。

插件内:用用户密码加密后写入 storage(思路示例)

import { ethers } from "ethers";

// 加密:助记词 + 用户密码 → 密文(仅示例,生产环境建议用 scrypt + AES 等标准 KDF/加密)
async function encryptMnemonic(mnemonic, userPassword) {
  const wallet = ethers.Wallet.fromPhrase(mnemonic);
  const json = await wallet.encrypt(userPassword);
  return json; // 可存入 chrome.storage.local
}

// 解密:用户输入密码后从 storage 取出密文,解密得到 Wallet,再 fromPhrase 或直接用私钥
async function decryptToWallet(encryptedJson, userPassword) {
  return ethers.Wallet.fromEncryptedJson(encryptedJson, userPassword);
}

注意:上述 encrypt 是单私钥的 Keystore;若存的是助记词,需要自己用 crypto.subtle 或库(如 scrypt-js + AES-GCM)做「密码 → 密钥 → 加密助记词」,再存到 chrome.storage.local,解锁时再解密出助记词、用 ethers 派生账户。


四、用户密码的作用

「用户密码」(钱包密码、登录密码)在浏览器钱包里不是助记词,不是私钥,也不参与助记词到种子的数学推导(除非你额外用了 BIP-39 的 passphrase)。它主要做这几件事:

  1. 解锁本地加密存储
    输入密码后,钱包用该密码解密存在本地的 vault/Keystore,把助记词或私钥加载到内存,才能签名、转账。不输入密码,恶意软件或他人拿到你的电脑,也拿不到明文助记词。

  2. 授权敏感操作
    很多钱包在「发送交易」「导出私钥」「显示助记词」等操作前会再次要求输入密码或做二次确认,避免在已解锁状态下被恶意页面或扩展滥用。

  3. 不参与「恢复」
    换设备或重装浏览器后,恢复钱包只需要助记词(以及可选的 BIP-39 passphrase),不需要旧设备的「钱包密码」。新设备上可以设一个全新的密码,只要助记词正确,就能导出同一批地址和资产。

简单说:用户密码是「本机保护层」,保护的是存在本地的密文;助记词是「跨设备恢复层」,谁掌握助记词谁就掌握资产。两者分工明确——密码丢了可以靠助记词在新环境恢复;助记词要是丢了或泄露,密码再复杂也没用。


五、小结

  • 助记词:按 BIP-39 从随机熵生成,带校验和,映射到 2048 词表,12/24 词对应 128/256 位熵;用于备份与恢复,谁持有助记词谁就能在兼容钱包里恢复整棵密钥树。
  • 私钥存储:可由助记词在内存中派生;或通过 Keystore(用户密码 + KDF + 对称加密)存成文件;浏览器钱包多用「用户密码加密的 vault(保险库)」存助记词或派生材料,避免明文落盘。
  • 用户密码:只负责解锁本地加密存储授权敏感操作,不参与助记词→种子的推导;换设备恢复只需助记词,不需旧密码。助记词与密码各司其职,助记词是资产恢复的根,密码是本地防护。