简介:面向使用 ImToken 及数字资产钱包、需要核对或恢复英文助记词的用户,这份资料围绕 2048 个英文助记词整理成查询与校对清单,可用于创建钱包后的助记词复核、恢复钱包时的单词定位,以及日常备份管理中的自查参考。资源包共 1 个 doc 文件,大小约 166KB,内容以连续的英文单词表为主,便于按字母顺序检索相近词形,减少因拼写偏差造成的记录错误;对助记词拼写不够熟悉、需在恢复前逐词确认的用户尤其适用。已有 11730 人学习,说明其在助记词查询场景中具有一定参考价值。文档还提示助记词由 12 至 24 个单词组成、关系钱包资产安全,强调离线保存、加密存储与定期备份等注意事项;读者可借助词表完成拼写比对、整理备份记录,并建立更谨慎的助记词管理习惯。
1. 搜「助记词大全」的人最后都撞上了什么:一个不存在的词表
「助记词大全」这个词组,我在帮人排查钱包恢复问题时被问过不止一次,问的人大多带着同一个预期:是不是存在一份清单,把别人家的助记词都收进去了,或者有个工具能"跑出来"。结论先摆在这里:这种东西不存在,而且不可能存在。BIP39 的英文词表是固定的 2048 个单词,12 个词的组合空间是 2 的 132 次方这个量级,把全世界的存储介质摞起来也装不下一份"大全"。按这个词去搜,落到的页面基本只有三类——伪造的生成器、要你填入已有助记词的"校验站"、以及把人引到下载页的假工具。这篇笔记讲清楚三件事:这套编码在数学上为什么凑不出大全、真正该做的本地离线校验长什么样、以及备份恢复这条链路上最容易翻车的地方在哪。
2. BIP39 的熵、校验位与 2048 词表:为什么「大全」在数学上凑不齐
先把"助记词"这个词拆开。它不是密码,也不是账号,而是一段随机数的可读编码。钱包里真正的根密钥是一串 128 到 256 位的随机熵,人脑记不住,于是标准规定了一套映射:把这串比特按 11 位一组切开,每一组当索引去一张 2048 词的固定表里取词。2048 正好是 2 的 11 次方,所以 11 位比特刚好对应一个词,不多不少。理解这一点,"大全"这个词的荒谬性就自然出来了——词表只有一张,公开的,谁都能下载;真正稀缺的是那串随机熵,而它是当场生成的,不在任何清单里。
2.1 从 128 位熵到 12 个单词:把编码链路摊开看
12 个词的助记词,源头是 16 字节也就是 128 位熵。生成流程分四步:先取 128 位随机数;再对这段随机数做一次 SHA-256,取结果的高 4 位作为校验位,拼到 128 位后面组成 132 位;然后把 132 位按每 11 位切成 12 段;最后每段的值落在 0 到 2047 之间,拿去查词表。校验位的长度不是随便定的,标准规定它等于熵长度除以 32,所以熵越长,校验位越多。
| 熵长度 ENT | 校验位 CS = ENT/32 | 总位数 ENT+CS | 词数 (ENT+CS)/11 |
|---|---|---|---|
| 128 | 4 | 132 | 12 |
| 160 | 5 | 165 | 15 |
| 192 | 6 | 198 | 18 |
| 224 | 7 | 231 | 21 |
| 256 | 8 | 264 | 24 |
上表这五个长度是标准允许的全部取值,除此之外的词数一律非法。很多新手以为"词越多越安全,那我随便凑 13 个词行不行",不行,13 个词连编码层都过不去。下面这段不依赖任何第三方库的实现,把整条链路完整跑一遍,看懂它比背十篇文章都管用:
import hashlib import secrets def entropy_to_mnemonic(ent: bytes, wordlist: list[str]) -> str: """把熵按 BIP39 编码成助记词;wordlist 必须是官方 2048 词,顺序不能改""" assert len(ent) in (16, 20, 24, 28, 32), "熵长度只能是 128/160/192/224/256 位" ent_bits = len(ent) * 8 cs_bits = ent_bits // 32 # 校验位长度 digest = hashlib.sha256(ent).digest() checksum = digest[0] >> (8 - cs_bits) # 只取 SHA-256 结果的高 cs_bits 位 n_words = (ent_bits + cs_bits) // 11 value = (int.from_bytes(ent, "big") << cs_bits) | checksum return " ".join( wordlist[(value >> (11 * (n_words - 1 - i))) & 0x7FF] for i in range(n_words) ) ent = secrets.token_bytes(16) # 只用 CSPRNG,别用 random print(entropy_to_mnemonic(ent, WORDLIST))这段代码里有两个参数值得盯住。secrets.token_bytes(16)的 16 是字节数,改成 32 就得到 24 词;中间那个cs_bits是由熵长度推出来的,不要手工传。digest[0] >> (8 - cs_bits)这一行是新手最容易写错的地方:SHA-256 返回 32 字节,校验位只取第一个字节的高几位,如果写成取低几位,生成的助记词在别的钱包里就会判定为"校验和不匹配"。0x7FF是 2047 的掩码,用来截取 11 位,写成0xFF就只能取到 8 位,词索引会错位。
2.2 2048 词表与校验位:抄错一个词为什么能被当场查出来
官方英文词表的设计有个很实用的约束:每个词的前四个字母在全表内唯一。这不是巧合,是为了让手抄和 OCR 有容错空间——你写下abandon和ability,只要前四位不同就不会混。词表本身是公开文件,任何钱包实现里都内置同一份,顺序也不能变,因为索引是按位置来的。
校验位的价值在恢复场景里体现得最明显。假设 12 个词里有一个抄错了,且错成的词仍在词表内,那么重新解码后得到的 132 位数据,校验位对得上的概率约为十六分之一,也就是说大约 93.75% 的情况下脚本会直接告诉你"校验和不匹配"。这就是为什么校验脚本比人眼可靠——它只做一件事,但对得毫不含糊。反过来也要说清楚边界:校验和通过只代表这 12 个词构成一个合法的 BIP39 助记词,不代表它对应任何真实存在的钱包。随机敲 12 个词,大约十六分之一能通过校验,但它们背后是一个空地址。很多骗局就建立在这个误解上,把"校验通过"包装成"这个助记词有效"。
2.3 枚举为什么走不通:把组合数摊开算一遍
12 个词的原始组合数是 2048 的 12 次方,即 2 的 132 次方,约 5.44×10³⁹。校验位把合法组合筛到 2 的 128 次方,约 3.40×10³⁸。这个数字是什么概念,用算力摆一下就清楚了:
| 每秒尝试的候选数 | 穷举 2¹²⁸ 所需时间(秒) | 折算成年 |
|---|---|---|
| 10⁶ | 3.4×10³² | 1.08×10²⁵ |
| 10⁹ | 3.4×10²⁹ | 1.08×10²² |
| 10¹² | 3.4×10²⁶ | 1.08×10¹⁹ |
| 10¹⁵ | 3.4×10²³ | 1.08×10¹⁶ |
表里最后一行已经是每秒一千万亿次的量级,放到现实中远超任何单机甚至任何集群能持续维持的吞吐,而它需要的年数仍然是 10¹⁶ 级别。作为对照,宇宙年龄的量级是 1.38×10¹⁰ 年,差了六个数量级。有人会提"我不是要穷举全部,我只要撞上一个有余额的地址"——这确实把难度降低了,但降低的倍数等于已知地址的数量。就算把某条链上所有历史地址都收进一张哈希表,命中概率也只是线性提升,所需的尝试次数依然是 2¹²⁸ 除以地址总数这个量级,而地址总数离 10¹⁸ 都还差得远。所以凡是宣称"用算法碰撞助记词"的工具,要么在跑一个注定空转的循环,要么真正的目的是让你把手里已有的助记词填进去。
3. 本地离线校验自己的手抄助记词:最小可跑脚本与参数
真正需要用脚本的场景只有一个:确认自己手上这份备份是对的。纸会受潮,笔迹会糊,隔两年再看,world和word分不清是常事。这一章给的是纯本地、不联网的校验流程,跑在一台断网的旧机器上,整个过程不产生任何对外请求。
3.1 先把环境弄干净:断网、隔离、关掉云同步
环境隔离不是形式主义。校验助记词意味着这串词会短暂出现在内存里,如果这台机器同时开着云剪贴板同步、输入法云联想、截图自动上传,等于把备份直接贴到了公网上。我一般会这么做:找一台不常用的旧笔记本,或者开一台虚拟机,装好系统后先断网,用 U 盘把依赖离线装好;把输入法切成纯本地模式,关掉云候选;退出所有同步客户端,包括网盘、便签、浏览器账号;操作全程不截图、不拍照、不粘贴到任何聊天窗口。
依赖只有两个库,一个是 BIP39 的编解码,一个是派生地址。离线机器上提前把包下好:
# 在能联网的机器上下载,不安装,只落包 pip download mnemonic bip_utils -d ./wheels # 拷到断网机器后本地安装,全程不访问网络 pip install --no-index --find-links=./wheels mnemonic bip_utils--no-index是关键参数,它强制 pip 只从本地目录找包,任何一次意外的外网请求都会直接失败而不是悄悄发出去。--find-links指向 U 盘里的目录,路径别带空格。
提示:校验脚本的运行目录不要放在任何自动同步的文件夹下,输出也不要重定向到文件。需要记录就手写。
3.2 校验和检查脚本:判断手抄那份到底错在哪
下面这段做三件事:检查词数是否合规、检查每个词是否在 2048 词表内、检查校验和。三层的顺序不能反,因为只有前两层过了,第三层的报错才有意义。
from mnemonic import Mnemonic MNEMO = Mnemonic("english") VALID_LEN = (12, 15, 18, 21, 24) def check_backup(phrase: str) -> tuple[bool, str]: words = phrase.strip().lower().split() # 第一层:词数 if len(words) not in VALID_LEN: return False, f"词数 {len(words)} 不在允许集合 {VALID_LEN} 内" # 第二层:词表 outside = [w for w in words if w not in MNEMO.wordlist] if outside: return False, f"不在 2048 词表内:{outside}" # 第三层:校验和 if not MNEMO.check(" ".join(words)): return False, "校验和不匹配,可能是词序错误或某个词抄错" return True, "校验通过" print(check_backup("你手抄的那 12 个词,空格分隔"))三个判断各管一段。词数不对,说明抄漏了或者多写了一行编号;词表不对,会直接把可疑词打印出来,这时候拿官方词表按前四位字母找,基本一眼能定位;只有前两层都过了,MNEMO.check的返回值才有诊断价值——它失败意味着这串词自洽性被破坏,最常见的两个原因是相邻两个词写反了、或者某个词写成了形近词。要提醒的是,check内部做的是完整解码加校验位比对,它不会联网,也不会去查这个助记词对应什么地址,这点可以放心。
如果词表那层报错,但你又看不出是哪个词写错了,可以做一个模糊匹配:把可疑词拿去和 2048 词表比编辑距离,距离为 1 或 2 的候选通常就是原词。这个操作最好也在离线机器上做,别用任何在线纠错服务。
3.3 派生地址核对:恢复后地址对不上,先查路径和口令
校验和过了只说明这张纸是合法的 BIP39 助记词,还不能证明它就是你那个钱包的备份。要证明这一点,得算出地址,和你记忆中的收款地址比一比。这里有两个参数会直接改变结果,一个是派生路径,一个是可选口令。
from bip_utils import ( Bip39SeedGenerator, Bip44, Bip44Coins, Bip44Changes ) phrase = "你校验通过的那 12 个词" passphrase = "" # 可选口令,多数钱包默认空字符串 seed = Bip39SeedGenerator(phrase).Generate(passphrase) # 以某条 EVM 兼容链的常用路径 m/44'/60'/0'/0/0 为例 addr = ( Bip44.FromSeed(seed, Bip44Coins.ETHEREUM) .Purpose().Coin().Account(0) .Change(Bip44Changes.CHAIN_EXT) .AddressIndex(0) .PublicKey().ToAddress() ) print(addr)Generate(passphrase)这个参数就是所谓的"第 25 个词"。传空字符串和不传是等价的,但只要当初设过口令,这里传空就会派生出完全不同的种子,进而得到一批完全不同的地址——这是恢复失败里占比很高的一类,后面避坑那章会单独讲。Account(0)、Change(...)、AddressIndex(0)三个数字拼起来就是路径尾段,改任何一个地址都会变。CHAIN_EXT表示对外收款链,有些实现里对应的是内部找零链,两者地址不通用。
实际核对时不要只比第一个地址。我会把AddressIndex从 0 到 4 各算一遍,五个地址里只要有一个能和历史记录对上,就能确认路径找对了。如果五个全对不上,先换路径,再查口令,最后才怀疑助记词本身。
4. 助记词的备份与恢复:介质、分片和一次真实演练
校验脚本解决的是"这份备份对不对",备份方案解决的是"这份备份到时候还在不在"。这两件事经常被混为一谈,导致很多人的助记词在纸上写得工工整整,两年后纸张受潮、字迹洇开,或者搬家时那张纸跟着某个纸箱一起消失了。这一章讲的是工程化的备份思路,不涉及任何具体产品。
4.1 介质选择与存放:三条不能破的原则
第一条原则是介质与场景分离。写在纸上便宜、方便,怕水怕火怕虫;刻在金属板上贵一些,能扛住高温和浸泡,但刻错一个字母就是灾难。常见做法是同时留两份,一份纸质放在日常能拿到的地方用于快速核对,一份金属的放在另一个物理位置作为长期存档。两份的内容必须完全一致,做完之后用第 3 章的脚本各校验一遍。
第二条原则是单一位置不存完整信息。把 24 个词整整齐齐写在一张纸上,等于把风险集中到一个点上。分片是更稳妥的做法:把词拆成两到三份,任意一份单独拿出来都不构成完整助记词,需要凑齐才能恢复。分片方案要么用标准化的门限算法,要么用最朴素的方式——比如 12 个词拆成前三词、中间六词、后三词,分别放在三个地方。朴素分片的安全性明显弱于门限方案,因为任何一份泄露都会缩小搜索空间,所以拆分粒度要自己想清楚。
第三条原则是存放位置不写暗示。很多人会在装助记词的袋子上写"钱包备份 2023",这个标签本身就是给偶然看到它的人一个明确的指引。中性化处理、不加任何说明,是成本最低的一层防护。
4.2 恢复验证的顺序:别在真金白银上做第一次试验
恢复这件事,最忌讳的是"从来没试过,出事那天第一次试"。合理的顺序是:先在离线机器上用脚本确认备份的校验和;再导入到一个干净的钱包环境里,看派生出的地址是否和历史地址一致;确认一致之后,用一笔小额做一次完整的转出测试;全部通过,这份备份才算真正可用。
这个顺序里第三步容易被跳过。地址对上了不代表签名链路没问题,有些环境会因为固件版本、链参数配置差异,在构造交易时出岔子。小额测试的成本很低,但能把这类的意外提前暴露出来。我一般建议每年做一次完整的恢复演练,用一次小额转账收尾,演练完把记录销毁。
4.3 可选口令与多签:能力边界要提前想清楚
可选口令(也就是常说的第 25 个词)能显著提升安全性:同一组 12 个词,配不同口令会派生出完全独立的钱包集合,被胁迫时还可以用一个"看起来正常"的口令交差。但它的代价同样明显——口令一旦忘记,助记词写得再工整也恢复不了,没有任何后门。所以用口令的人必须单独为口令设计一套备份方案,且这套方案不能和助记词的备份放在一起。
多签是另一条路,把控制权分散到多把密钥上,避免单点失效。它的复杂度不在生成,而在恢复:参与方的公钥、门限值、签名顺序,这些信息在恢复时缺一不可。我的经验是,多签方案必须配一份文字版的恢复手册,写清楚每一步谁做什么,这份手册要和密钥分开存放。任何"到时候再说"的多签,出事时基本都会卡住。
5. 排查:助记词相关的五类翻车现场
这一章是我自己踩过和帮别人收拾过的坑,按现象、原因、解决三段写。每一条都对应前面章节里的某个参数,遇到问题时先来这里对号入座。
5.1 校验和始终不过,但词看着都对
现象:脚本报"校验和不匹配",把 12 个词反复核对,每一个都在词表里,拼写也没错。
原因:九成是词序问题。手抄时为了整齐,有人会按字母顺序重排,或者抄成两列之后按列读,顺序就乱了。另一类原因是形近词替换,比如把world写成word,两个词都在词表内,肉眼极难分辨。校验位只对整串数据负责,它不告诉你错在哪一位。
解决:先按原始顺序逐词比对,确认没有重排;再用编辑距离把每个词和词表做模糊匹配,找出距离为 1 的候选;如果还是不行,用二分法定位——保留前 6 个词不动,把后 6 个词换成任意合法组合补齐,逐个试,看哪一段改动后能通过校验。这个过程很枯燥,但比重抄一份可靠。
5.2 恢复后地址全变了,助记词明明是同一份
现象:导入同一组助记词,得到的地址和原来完全不同,历史余额归零。
原因:两个参数之一出了问题。要么当初设过可选口令而这次没填,要么派生路径不一样。有些钱包默认用m/44'/60'/0'/0/0,有些用m/49'或m/84'开头,还有些把账户索引放在别的层级。路径不同,同一个种子会派生出完全不同的地址集合。
解决:先确认有没有口令,这需要回忆当初的设置,没有捷径;再遍历常见路径,配合AddressIndex从 0 扫到 4,看哪个组合能对上历史地址。如果手上有任何一笔历史交易的收款地址,拿它做比对最直接。
5.3 抄在金属板上,结果刻错了一个字母
现象:金属备份看着很稳妥,某次校验发现有一个词和词表里的拼写差一个字母。
原因:刻字工具的字体和手写差异大,rn和m、l和I、0和O这类混淆在金属上尤其明显。另外刻的过程中断句位置变了,词与词之间的分隔丢失,重读时容易合并。
解决:刻之前先在纸上定稿并跑一遍校验脚本,确认无误再动工具。刻完立刻用第 3 章的脚本重新校验一次,别等到需要恢复时才发现。词与词之间留固定间距,或者用短横线分隔,避免重读时粘连。
5.4 把助记词粘进"在线校验工具",之后资产被转走
现象:搜"助记词校验"找到一个网页,输入 12 个词点了"检查",页面提示格式正确,几天后资产被转走。
原因:这类站点存在的唯一目的就是收集。校验和这件事完全可以在本地算,任何要求你把助记词提交到服务器的工具,无论界面做得多正规,都不该用。类似的还有伪装成"恢复助手"的应用、要你导入助记词才能"检测风险"的插件。
解决:一旦粘过,立刻把这组助记词对应的资产转移到一组全新的、在离线环境里生成的助记词下。旧的那组永久作废。不要试图去"删掉"什么,链上没有删除这回事。
5.5 聊天记录里的截图,成了最完整的一份备份
现象:整理旧手机时发现相册里有一张助记词的截图,而纸质的备份早就找不到了。
原因:备份时图省事拍了照,之后照片被自动同步到云端,跟着账号在多个设备间流转。这类泄露最隐蔽,因为当事人往往认为"我从来没给别人看过"。
解决:发现后按泄露处理,迁移资产并重新生成。日常备份流程里应该明确禁止拍照、截图、粘贴到任何输入框,包括自己的备忘录。要记录就手写,写完把草稿销毁。
6. 把校验做成习惯:我的离线自检清单与一个重复利用的技巧
前面几章零散提到的东西,落到日常其实就是一张纸的事。我自己用的清单只有五行:助记词是否在离线机器上生成;校验脚本是否跑过并通过;纸质与金属两份内容是否逐词一致;可选口令是否有独立于助记词的备份;上次恢复演练距今是否超过一年。这五行每季度对一遍,花不了十分钟,但能把绝大多数事故挡在发生之前。
有个技巧值得单独说:把 2048 词表存成一份纯文本放在离线机器上,配一个十行的模糊匹配脚本。手抄件出问题时,不用眼睛逐个比对,直接把可疑词丢进去算编辑距离,输出三到五个候选。这个脚本我用了很久,救回过两份差点被判定为"报废"的备份。它的价值在于把"我怀疑抄错了"这种玄学判断,变成一个可以反复执行的动作——机器不会疲劳,人眼盯到第三遍就开始自我说服了。
还有一件事我吃过亏:不要等到"需要用"的时候才第一次跑校验。备份做完当天跑一次,三个月后再跑一次,一年后再跑一次。中间任何一次失败,你还有时间补救;等到资产转不出去的那天才发现备份有问题,那才是真的没有后悔药。我现在的习惯是每次换设备、每次升级环境之后都重新校验一遍,把它当成开机自检一样的东西,不指望它有用,但它在,心里踏实。
这套东西的门槛其实很低,一台旧机器、两个离线包、一段不到五十行的脚本就够了。真正难的不是技术,是把它变成习惯。希望帮到你。
本文还有配套的精品资源,点击获取