私钥 → 非压缩 WIF
对载荷 0x80 ‖ k 做 Base58Check 编码,得到最初的 51 字符、以 5… 开头的钱包导入格式字符串 —— 老式纸钱包上印的就是它,它隐含非压缩公钥,因而也隐含那个遗留的 1… 地址。
请在上方输入内容后点击「转换」。不知道填什么?点「填入示例」即可载入占位符里的演示数据。
本页计算了什么
你输入一个 256 位私钥,本页给出它的非压缩 WIF —— 也就是最初的钱包导入
格式字符串:51 个字符,以 5 开头,内部不含压缩标志。2012 年年中之前的所有比特币备份都用这个
格式,印在老式纸钱包上的也还是它。
把它和现代形式放在一起看:压缩 WIF 是
Base58Check(0x80 ‖ k ‖ 0x01) —— 多一个字节、多一个字符、校验和不同,隐含的地址也完全不同。
1. 最初的 WIF:那时公钥只有一种形状
第一个比特币客户端诞生时,公钥只有一种序列化形式:OpenSSL 不做任何选择就产出的那个 65 字节
04 ‖ X ‖ Y。没有压缩形式、没有标志位、也没有任何可选项。因此私钥需要携带的元数据只有一项 ——
它属于哪个网络(也就是哪种币)—— 此外什么都不需要。
由此得到的设计极其精简,而且一旦看懂就觉得理所当然:
- 前面一个版本字节,主网为
0x80,用来表明这个字符串是私钥而不是地址。 - 32 字节原始密钥,大端序,左补零到固定宽度。
- 末尾 4 字节校验和,让人类抄写造成的错误在钱包真正使用这把密钥之前就被拦下来。
最后用 Base58 编码,好让人能念、能敲,也避开形近字符。整个格式就这么多。名字「Wallet Import Format」 是后来才有的;编码本身从早期客户端就存在。请注意其中缺少什么:没有标志字节,因为当时没有任何东西 需要标记。这不是谁为老密钥设计的「遗留模式」—— 它就是原始格式,一字未改,而 2012 年的压缩形式是作为它的 扩展被造出来的。
0x80 不等于主网 P2PKH 地址开头的 0x00,也不等于非压缩公钥
标记的 0x04。同一条推导链上会出现三种不同的单字节头部。版本字节告诉钱包「这是一把主网私钥,
用的是最初的编码」,其余一切由此推出。
2. 去掉标志位为什么会改变载荷长度、首字符和校验和
同一把密钥的压缩 WIF 与非压缩 WIF,在载荷中只相差一个字节,而这一个字节带来四个可见的后果。
| 后果 | 非压缩 WIF | 压缩 WIF |
|---|---|---|
| 载荷长度 | 33 字节(0x80 ‖ k) | 34 字节(0x80 ‖ k ‖ 0x01) |
| 送进 Base58 的字节 | 37 字节 = 296 比特 | 38 字节 = 304 比特 |
| 字符串长度 | 51 个字符 | 52 个字符 |
| 首字符(主网) | 永远是 5 | K 或 L |
| 校验和(演示密钥) | b6f3d7f5 | 3a0a0417 |
| 隐含的地址(演示密钥) | 16kR3eis…WG2G | 146ZNjH7…2UqT |
每一条都是机械推出来的:
- 长度。 Base58 编码的是一个大整数,每个字符携带 log258 ≈ 5.858 比特。 296 / 5.858 ≈ 50.5,所以 37 字节最多需要 51 个字符;304 / 5.858 ≈ 51.9,所以 38 字节最多需要 52 个。 多一个字节,正好多一个字符。
- 首字符。 51 个字符时,首位 Base58 数字是
floor(值 / 5850)。 主网非压缩 WIF 永远以字节0x80开头,所以它的值落在[2295, 2295 + 2288)内;而5850 ≈ 2292.899,商在约 4.29 到 4.32 之间,对任何合法密钥取整都是 4 —— 也就是字符5。测试网上版本字节是0xef, 同样的算术给出9。5不是约定,是被算术逼出来的。 - 校验和。 校验和是
SHA256(SHA256(载荷))的前四字节,而载荷本身变了。 输入一变,哈希就完全无关,所以字符串末尾那四个校验字符与压缩版本毫无关系。 - 地址。 标志位是一句承诺:承诺钱包该推导哪种公钥。没有它,钱包推导
04 ‖ X ‖ Y,对 65 字节而不是 33 字节做哈希,落到另一个 20 字节承诺值上 —— 也就是另一个 地址。
3. 完整的字节布局
| 偏移(待编码输入) | 长度 | 字段 | 演示值 | 说明 |
|---|---|---|---|---|
| 0 | 1 字节 | 版本字节 0x80 | 80 | 主网私钥;测试网是 0xef |
| 1 – 32 | 32 字节 | 私钥,大端序 | 0824c31477…07a171ca | 固定 32 字节,保留前导零 |
| — | 0 字节 | 压缩标志 —— 不存在 | — | 正是这个「不存在」定义了非压缩形式 |
| 33 – 36 | 4 字节 | 校验和 | b6f3d7f5 | SHA256d(第 0–32 字节) 的前 4 字节 |
| 37 字节 | 33 字节载荷 + 4 字节校验和 → 51 个 Base58 字符 | |||
对演示密钥,校验和的计算过程值得完整看一遍,因为正是这一步把字符串与密钥绑定在一起:
| 阶段 | 值 |
|---|---|
| 载荷(33 字节) | 800824c314772b2c2859c889471390a36bf66e53a1ca1642f96f0f2c9307a171ca |
| SHA256(载荷) | 0f5261d28f2887da16ac302c8f0593c885d57a538afd35f5067322b0e5f2fc96 |
| SHA256(SHA256(载荷)) | b6f3d7f5f57bbbced3c64757bda8ac500a5fa6a346c278f65af7f84a865da824 |
| 校验和(前 4 字节) | b6f3d7f5 |
| 交给 Base58 的最终 37 字节 | 800824c314772b2c2859c889471390a36bf66e53a1ca1642f96f0f2c9307a171cab6f3d7f5 |
4. 为什么 5… 格式如今被视为历史遗留
2012 年并没有让这个格式失效。改变的是经济账与整个生态:
| 维度 | 非压缩(5…) | 压缩(K…/L…) |
|---|---|---|
| 花费时嵌入的公钥 | 65 字节 | 33 字节 |
| 典型 P2PKH scriptSig | 1 + 72 + 1 + 65 = 139 字节 | 1 + 72 + 1 + 33 = 107 字节 |
| 每个输入多付的手续费 | 比压缩形式多约 32 vbyte | 基准 |
| SegWit(P2WPKH、P2SH-P2WPKH) | 不可能 —— witness v0 要求压缩公钥 | 支持 |
| Taproot(BIP340 / BIP86) | 不使用;Taproot 定义在 32 字节 x-only 公钥上 | 标准输入 |
| 派生钱包支持 | 只能作为孤立的遗留密钥导入 | 所有 HD 钱包原生支持 |
| 还会被默认生成吗 | 2012 年之后没有任何钱包这么做 | 到处都是 |
所以 5… 密钥并不是坏的,只是又贵又别扭。它享受不到 SegWit 的费用折扣,无法支撑 Taproot
输出,而且在它余生的每一次花费中都要多付约 32 个虚拟字节的见证折扣后权重。钱包因此不再生产它,它所对应的
地址类型也被贴上了「遗留」标签 —— 这个词描述的是流行度,不是有效性。
5. 清扫(sweep)难题详解
这才是本页真正的核心。你有一张 2011 年印出来的老纸钱包,上面是一个 5… WIF 和一个
1… 地址,你想把币搬进现代钱包。可能发生三件事:
- 钱包直接拒绝这把密钥。 许多现代钱包 —— 尤其是基于输出描述符(descriptor)构建的, 以及某些硬件钱包的配套 App —— 只支持压缩密钥的导入账户。它们会回答「无效私钥」「不支持的密钥格式」, 或者干脆毫无反应。密钥本身没问题,只是软件里没有这条代码路径。
- 钱包收下了,却显示余额为零。 这是最危险也最常见的情况。钱包导入了那 32 字节密钥,
默认采用压缩形式(它唯一会推导的形式),算出
hash160(02/03‖X),盯着146ZNjH7…这类地址,然后什么也没找到 —— 因为你的币在非压缩地址上。你得到的结论等于 被告知这张纸钱包是空的。而且从钱包确实知道的那个地址清扫同样不可能,原因相同:它无法为一个 脚本中承诺了 65 字节公钥的输出签名。 - 钱包正确接受。 它把这把密钥当作「遗留密钥」账户导入,推导非压缩地址、监控它, 并用 65 字节公钥签名花费。有些钱包做得完全正确;这个功能通常叫「导入遗留密钥」 「清扫纸钱包」或「导入非压缩密钥」。
第 2 种情况就是人们口中所说的「我的比特币不见了」。它几乎从来不是真的。你手上的私钥依然控制着那个 非压缩地址,你只是需要能由它推导非压缩公钥的软件。在采取任何激烈措施之前,先把情况查清楚:从密钥算出 非压缩地址(本页与私钥 → P2PKH 非压缩地址都会算),再到区块浏览器上查这个 确切地址。如果那里有币,就使用提供遗留密钥或纸钱包清扫功能的钱包/工具,用一笔交易把全部余额转到现代钱包 里的新地址上。
第 2 种情况还有个近亲陷阱:某个钱包接受了 5… 密钥,却悄悄把它「升级」,把
压缩地址当成你的新收款地址。如果你随后往那个压缩地址转币,你纸钱包上的旧余额和新余额就
落在两个不同地址上,而下次打开的钱包可能只监控其中一个。往任何地址转币之前,永远先确认钱包显示的地址
与你的预期是否一致。
6. 怎么判断币到底在哪种形式上
WIF 的首字符告诉你的是导出者的意图,而不是别人往哪里付过款。这是两个不同的问题, 而只有链上数据能回答第二个。
| 你手上有什么 | 它能告诉你什么 | 该去查什么 |
|---|---|---|
以 5 开头的 WIF | 导出者意图是非法压缩形式 —— 它的校验和与长度都印证了这一点 | 先查非压缩地址,也查一下压缩地址,以防有人往那里付过款 |
以 K 或 L 开头的 WIF | 意图是压缩形式 | 先查压缩地址,非压缩地址作为备用 |
以 1 开头的地址 | 只能说明它是主网 P2PKH 地址 —— 两种形式都会产生 1… 地址 | 用密钥把两个地址都算出来,与手上这个逐字比对 |
| 裸十六进制私钥 | 关于编码,什么也说明不了 | 两个地址都查;币在哪一个,就必须用哪一种形式去花 |
| 一个空纸钱包地址 | 币已被转走,或从未到账 | 由同一把密钥推出的另一个地址,以及交易历史 |
两条实用经验:(a) 纸钱包上印的地址与印的密钥,形式上几乎总是一致的 —— 5… 密钥配的是由
65 字节公钥构造的地址;(b) 当恢复结果看起来是空的,绝不要凭一个地址下结论。把两种都推出来、两个都查,
然后再决定。
7. 用真实演示数据演算一遍
以下全部是输入框里那个示例私钥的真实输出:
| 项目 | 值 |
|---|---|
| 私钥 k | 0824c314772b2c2859c889471390a36bf66e53a1ca1642f96f0f2c9307a171ca |
载荷 0x80 ‖ k(33 字节) | 800824c314772b2c2859c889471390a36bf66e53a1ca1642f96f0f2c9307a171ca |
| SHA256(SHA256(载荷)) | b6f3d7f5f57bbbced3c64757bda8ac500a5fa6a346c278f65af7f84a865da824 |
| 校验和 | b6f3d7f5 |
| 非压缩 WIF | 5HssbguBnjbaUVZCsH9YuzUG7T4vYQf51iiodi4izdVy6aVNekU |
| 长度 / 首字符 | 51 个字符,以 5 开头 |
| 非压缩公钥 | 04ff812e26116a9aa140abe629e7f8a38401653caf925119def59ed3758c67ee808f49cde13c7ffd64f1d730bf87a743a578eda4971ddac4a08118160732b424ae |
| 它的 hash160 | 3f0e966dc089c611a9c1d03bd4f69ea53b0223f9 |
| 隐含的 P2PKH 地址 | 16kR3eiswUY6tmGnxZhwQmW6LAvTLGWG2G |
| 对照:同一把密钥的压缩 WIF | KwVYL77Lcs1ckM39NvGjrtfKhU4KKdR2iB9Wq2FSMN6rbGK5tVqG(52 个字符,以 K 开头) |
| 对照:压缩地址 | 146ZNjH7XTXnMd1ofe3z7CL2i8WM7N2UqT |
| 测试网非压缩 WIF | 91eWBRijNxfiSZ4VVd3Tnb2Dm7RdhaCGMfakiLRELNF1saLqhym |
| 测试网非压缩地址 | mmGNLhorkVyMfskQg8gKEgiRCAXAGnxeBv |
地址就是对那 65 字节密钥套用同一套 Base58Check 配方得到的,所以它自己的载荷也能列出来:
版本 00、hash160 3f0e966dc089c611a9c1d03bd4f69ea53b0223f9、校验和
3b0b7cbd,以及 34 个字符的结果 16kR3eiswUY6tmGnxZhwQmW6LAvTLGWG2G。
8. 往返验证
本页会用 Btc::wifDecode() 解码自己的输出,并在结果面板里显示还原出的每一个字段,让你看清
没有任何东西丢失或被凭空造出来:原始 32 字节密钥、为 false 的压缩标志、版本字节
80、主网、有效的 b6f3d7f5 校验和,以及 33 字节载荷。注意解码规则有多简洁 ——
并不存在一个显式的「非压缩标记」字节,载荷的长度本身就是标记:33 字节表示非压缩,34 字节且以
0x01 结尾表示压缩,其它长度一律拒绝。
9. 压缩 WIF 与非压缩 WIF 对照
| 非压缩 WIF(本页) | 压缩 WIF | |
|---|---|---|
| 公式 | Base58Check(0x80 ‖ k) | Base58Check(0x80 ‖ k ‖ 0x01) |
| 载荷 / 总字节 | 33 B / 37 B | 34 B / 38 B |
| 字符数 | 51 | 52 |
| 首字符(主网/测试网) | 5/9 | K 或 L/c |
| 引入时间 | 2009 年最初的客户端 | Bitcoin 0.6.0,2012 年 3 月 |
| 隐含的公钥 | 04 ‖ X ‖ Y,65 字节 | 02/03 ‖ X,33 字节 |
| 隐含的地址(演示密钥) | 16kR3eis…WG2G | 146ZNjH7…2UqT |
| 能否用于 SegWit / Taproot | 不能 | 可以 |
| 费用影响 | 每个输入多约 32 vbyte | 基准 |
| 典型出现场合 | 老纸钱包、2012 年前的备份 | 所有现代导出 |
10. 安全须知
5…WIF 就是明文私钥。 Base58 只是换了字母表,不是加密。任何拍到纸钱包、 扫到二维码或者看到你屏幕的人都能花掉那些币。- 校验和只防笔误。 四字节 SHA256d 能抓住抄写错误,但对「这个字符串是谁造的、这把密钥 当初是否被诚实地生成」一无所知。一个「完全合法」的 WIF 也可能属于攻击者。
- 老密钥有太长的时间可以泄漏。 一把在 2011 年的钱包文件、发给自己的邮件、云备份或相册里 躺过的密钥,十多年间暴露在无数攻击面之下。清扫老密钥时,用一笔交易把全部余额转到新生成的地址 上 —— 不要把找零或部分金额留在旧地址,事后也绝不要复用这把旧密钥。
- 警惕「清扫服务」。 任何声称能帮你清扫纸钱包的网站,本质上都是在索要你的私钥。 诚实的这种服务并不存在,因为索取这个动作本身就是盗窃手法。请用你自己掌控的软件清扫,能离线就离线。
- 扫到正确的形式上。 把旧币搬进现代钱包时,请确认目标地址是你做过备份的地址 (由种子派生的地址),而不是从你正打算退休的那张纸钱包密钥推导出来的压缩地址。
11. 常见错误
- 因为现代钱包拒收,就以为
5…WIF 是无效的。 它是原始格式、完全正确、 可以花费;只是那款软件不支持。 - 以为余额为零就代表币没了。 通常只代表钱包推导的是压缩地址。把两个都算出来。
- 以为密钥需要「升级」。 密钥无法升级,能搬的只有币。私钥没有版本、也没有状态 —— WIF 只是它的写法。
- 误用老密钥的压缩 WIF。 它会给出一个合法但不同的地址,这是让真实存在的币看起来消失的 最干净的办法。
- 手工把 WIF 截短到 51 个字符。 长度不是装饰:33 字节载荷与 34 字节载荷的哈希不同, 手工裁剪过的字符串过不了校验和。
- 指望
5…密钥能用 SegWit。 witness v0 要求压缩公钥,所以bc1q…地址对非压缩密钥来说是够不着的。
12. 速查表
| 项目 | 值 |
|---|---|
| 编码方式 | Base58Check:载荷 ‖ SHA256d(载荷) 的前 4 字节 |
| 载荷 | 0x80 ‖ k(32 B) —— 没有压缩标志 |
| 载荷 / 编码长度 | 33 B / 37 B |
| 输出 | 51 个 Base58 字符,首字符 5(主网) |
| 测试网变体 | 0xef ‖ k,首字符 9 |
| 隐含的公钥 | 65 字节,04 ‖ X ‖ Y |
| 隐含的地址 | 由 hash160(04‖X‖Y) 得到的 P2PKH |
| 靠什么解码 | 仅凭载荷长度(33 = 非压缩,34 且带 0x01 = 压缩) |
| 可逆吗 | 可以 —— 32 字节密钥被精确还原 |
| 链上仍然有效吗 | 在旧式 P2PKH 脚本中有效 |