协议演进 / BIP/比特币改进提案 / BIP-38
BIP-38
把私钥用口令加密后编码成 58 个字符、以 6P 开头的字符串,让纸钱包和实体比特币做到“实物与口令”双因子,口令不对谁也花不走。本 BIP 目前处于已部署状态。
一、档案卡
| 编号 | BIP-38 |
|---|---|
| 标题 | Passphrase-protected private key |
| 作者 | Mike Caldwell <[email protected]>, Aaron Voisine <[email protected]> |
| 指定日期 | 2012-11-20 |
| 层级 | Applications(应用) |
| 类型 | Specification(规范类) |
| 状态 | Deployed(已部署) |
| 阅读版 | https://bips.dev/38 |
| 官方原文 | https://github.com/bitcoin/bips/blob/master/bip-0038.mediawiki |
二、放在哪一族
BIP-38 属于私钥的编码与保管这一族。它要标准化的不是链上格式,而是“私钥离开电脑、印到纸上或装进实体币里时”以什么形式存在。
近邻是未加密私钥的 WIF(Wallet Import Format)格式:原文特意把加密记录的前缀定为以 6 开头、6P 起头,与 WIF 常见的 5 开头区分开来——6 的含义被解释为“这把私钥还需要别的东西才能使用”,P 则提示所缺的第二因子是口令(passphrase)。
它与 BIP-39 分工不同:BIP-39 管的是种子助记词的备份;BIP-38 管的是单个私钥的加密记录,主要服务纸钱包与实体比特币场景。
三、它要解决什么
动机来自作者对实体比特币与纸钱包实际用法的观察:
- 对发行方的不信任难题:发行实体比特币的一方必须既可信、又被信任;即便发行方本身可信,用户怀疑“理论上有能力拿走资金的第三方”也是正当的。一枚发行方也破解不了的实体比特币,内在价值高于一枚发行方能破解的;
- 双因子实体币不够好用:想安全持有比特币、又不想攀登自建安全环境的技术学习曲线的人,需要一种能装进盒子、在市场上出售的双因子方案。当时的做法是用户自备私钥、把公钥交给发行方、收到实体币后还必须把自记的私钥与币放在一起保管并靠专用工具赎回——实体币的便利基本被抵消;
- 人对人传递的风险:把装有比特币的纸钱包寄出去,若口令改走电话或邮件等另一条通道告知,任何单一通道被截获都偷不走钱;把加密纸钱包放在银行保险箱、口令留家里或分给可信的人,也能防保管场所的人监守自盗。
标准化口令加密的私钥格式,意义在于赎回时不必依赖某一家提供的专用工具:格式统一,各处钱包都应能认、能解,用户只需保管一个自己选的、比私钥短得多、甚至可以刻在实体币上的口令。
四、规则本身
4.1 记录长什么样
加密后的私钥记录是一串 58 个字符的 Base58Check 可打印字符串,恒以 6P 开头。字符串里包含重建私钥所需的全部信息,只差口令本身。
记录内还以明文编入结果比特币地址的 32 位哈希:不知道口令的人也能据此以相当高的概率把记录与某个比特币地址对应起来;完整的比特币地址则只能在成功解密后导出。
抗暴力破解靠两样东西:加盐,以及用 scrypt 做口令派生,让每次试猜都付出可观的计算代价。
载荷共 39 字节(不含 Base58 校验):对象标识前缀 2 字节(非 EC 乘法为 0x0142,EC 乘法为 0x0143)、1 字节标志(flagbyte,含压缩公钥标志、EC 乘法标志、lot/sequence 标志等)、4 字节地址哈希、其余为加密后的密钥材料。原文说明,AES 加密不使用初始化向量(IV),类似 IV 的材料由 scrypt 从口令与地址哈希盐中导出。地址哈希由结果地址的双重 SHA256 取前 4 字节,既作盐,也作输错口令时的校验。
4.2 模式一:非 EC 乘法——加密任意已知私钥
优点是任何已知的私钥都能用任意口令加密,执行加密的一方必须知道口令。步骤要点:
- 算出比特币地址,取其双重 SHA256 的前 4 字节为 addresshash;
- 用 scrypt 从口令派生 64 字节:盐为 addresshash,参数 n=16384、r=8、p=8(原文注为暂定值),结果对半分为 derivedhalf1 与 derivedhalf2;
- 私钥两半分别与 derivedhalf1 对应部分异或后,用 derivedhalf2 作密钥做 AES-256 加密,拼成记录。
解密时逆序操作,最后由解出的私钥重算地址,比对记录中的 addresshash 是否一致,以判断口令输对没有。
4.3 模式二:EC 乘法——制作者也不知道口令
这种模式支持“共享生成”:生成最终密钥串与地址的一方(如实体比特币制造商)只知道一个由原始口令派生出的字符串,不知道口令本身;真正赎回仍需原始口令。它不能用来加密一个已知的私钥——生成加密记录的过程同时就是生成新地址的过程。原文指出这反过来也是一项安全收益:持有人若确信口令够强且只有自己知道,就能确信没人能知道该地址的私钥。
流程角色分工:知道口令的受益人称 owner(所有者),他先生成称为中间码(intermediate code)的东西交给 printer(制作者)。中间码以 Base58Check 编码、字符串以 passphrase 开头,里面装着所有者熵(ownerentropy)与由口令经 scrypt(n=16384、r=8、p=8,输出 32 字节)等步骤派生出的 EC 点 passpoint。制作者再随机生成 seedb,经 EC 乘法与第二轮 scrypt(n=1024、r=1、p=1)和 AES 加密,产出地址与加密记录,却算不出私钥。
中间码可选地嵌入 lot(批次)与 sequence(序号):两者合并为 32 位数,20 位给 lot(0 到 1048575)、12 位给 sequence(0 到 4095),用于防制作者在批量生成时做手脚或出错。
制作者还可以回给所有者一个确认码(confirmation code):75 个字符、以 cfrm38 开头。所有者凭口令和确认码可独立验证“这个地址确实依赖于我的口令”,并核对 lot 与 sequence,确信制作者没有给一个与口令无关、能被制作者自己花掉的地址。
4.4 与旧格式的关系
这是新标准,与向后兼容关系不大,至多是扩展了 WIF。原文假定私钥输入入口同时也接受十六进制、WIF 等既有格式;本格式在外观上不会与任何既有格式混淆,保留了自动识别的可能。原文还提醒山寨链实现者不要挪用未用的标志位表示链归属,应利用地址哈希来区分。
原文另有一节讨论 scrypt 参数的取舍:参数要在“高效实现每次也要耗费可观时间”与“用 JavaScript 等慢速解释语言实现的用户等上几秒也可接受”之间平衡,并提到若赎回在服务器端做,几秒的 CPU 消耗会打开拒绝服务面,因此更适合把解密放在用户浏览器端完成。
五、谁必须动
普通持币人:要动的是保管方式:纸钱包或实体币保管“实物”这一因子,口令保管“记忆”这一因子,两者分开存放;口令遗忘意味着记录无法解开,格式本身没有找回通道。
纸钱包与实体币制作者:按本格式生成记录;用 EC 乘法模式时,只接触中间码与确认码流程,始终接触不到口令与私钥。
钱包开发者:要能识别以 6P 开头的记录、执行 scrypt 与 AES 解密、校验地址哈希,并处理压缩与未压缩公钥、lot/sequence 等标志位,才能让用户在别处赎回。
全节点与共识层:完全不动。本 BIP 是纯粹的钱包侧私钥存储格式,链上交易与地址的规则没有任何改变。
六、现在算不算数,以及一个常见误读
状态为 Deployed。BIP-38 格式的加密纸钱包在比特币早期被实际印制与流通,6P 开头的字符串至今仍能被识别。需要注意的是,其预设场景——纸钱包与实体比特币——在今天已不是主流保管方式,主流已转向 BIP-39 助记词加 BIP-32 分层钱包;但作为档案,BIP-38 记录的标准格式仍然有效,持有这类纸钱包的人赎回时靠的正是它。
常见误读:
“私钥被 BIP-38 加密过,就可以随便拍照、上传、托人保管,反正没口令解不开。”
不对。加密记录的设计前提就是会被人拿到——它抵抗的是“拿到记录但没有口令”这一种情形,靠的是 scrypt 把试猜变贵,而不是让试猜变得不可能。口令若短、若常见,拿到记录的人可以在离线环境里不受次数限制地慢慢穷举,记录中的明文地址哈希还正好充当每轮猜测的对错判据。实物与口令要分开保管,口令本身必须够强,缺一不可。
七、延伸
- 阅读版:https://bips.dev/38
- 官方原文:https://github.com/bitcoin/bips/blob/master/bip-0038.mediawiki
- 相关:BIP-32 分层确定性钱包、BIP-39 助记码
- 仓库总目录:https://github.com/bitcoin/bips
