私钥 → 压缩 WIF
对载荷 0x80 ‖ k ‖ 0x01 做 Base58Check 编码,得到 52 个字符、以 K…/L… 开头的钱包导入格式字符串。它告诉钱包要推导压缩公钥 —— 这是现代默认形式,也是所有支持 SegWit/Taproot 的单密钥导入背后的格式。
请在上方输入内容后点击「转换」。不知道填什么?点「填入示例」即可载入占位符里的演示数据。
本页计算了什么
你输入一个 256 位私钥,本页给出它的压缩 WIF —— 也就是那个以
K 或 L 开头、长度 52 个字符的钱包导入格式字符串,它告诉钱包要由这把私钥推导
压缩公钥。WIF 不是新的秘密,也不是新型密钥:它就是你的私钥,加上两个字节的元数据,再加一个
校验和,用 Base58 写出来而已。
上面结果面板把这条链的每一环都单独列了出来:载荷、载荷的每个字段、哈希中间值、校验和,以及最终字符串。
1. Base58 是什么,以及字母表为什么跳过 0 O I l
Base58 是 58 进制的位值制表示 —— 和十进制、十六进制是同一个思路,只是把字母表换成了精心挑选的 58 个 字符。编码一个字节串,就是把它当成一个巨大的整数,不断除以 58 收集余数;解码则反其道而行。由于字母表 区分大小写且不含任何标点,一个 base58 字符串可以直接念出来、从纸上一字一字敲进去, 或者塞进二维码而无需转义。
| 字母表分段 | 字符 | 数量 | 故意缺席的字符 |
|---|---|---|---|
| 数字 | 1 2 3 4 5 6 7 8 9 | 9 | 0(与 O 混淆) |
| 大写字母 | A B C D E F G H J K L M N P Q R S T U V W X Y Z | 24 | I(与 1、l 混淆)、O(与 0 混淆) |
| 小写字母 | a b c d e f g h i j k m n o p q r s t u v w x y z | 25 | l(与 1、I 混淆) |
| 合计 | 58 | 9 + 24 + 25 = 58 | |
这四个被剔除的字符,正是这套字母表存在的全部理由。比特币的密钥和地址是要靠人手抄写的 —— 从屏幕上抄、
从纸质备份上抄、从金属助记板上抄 —— 而最常见的抄写错误恰恰就是
0↔O、1↔I↔l。把容易混淆的字形直接从字母表里
拿掉,等于从源头消灭了一整类错误,而不是等到事后去检测它。
还有两个性质在实践中很重要:
- 前导零字节会被编码成
1。 纯大整数编码会丢掉前导零,所以 Base58 把每一个 前导0x00字节编码为一个字面字符1(字母表下标 0)。这就是为什么所有主网 P2PKH 地址(版本字节是0x00)都以1开头,也是为什么满屏都是1的字符串完全正常。 - WIF 永远不会以
1开头。 它的首字节是0x80,最高位为 1, 因此没有前导零字节可编码。
2. 为什么需要校验和,以及它到底怎么算
光有 Base58 没有任何检错能力:改掉一个字符,你会得到一个完整无损、格式完全正确的另一个数字 —— 对私钥来说,这要么意味着另一把密钥,要么意味着某个钱包会甩给你一句莫名其妙的报错。因此比特币在编码之前 先追加 4 字节校验和,这套方案就叫 Base58Check:
SHA-256 被应用两次(也就是比特币用于区块哈希和交易 ID 的 SHA256d),结果截断为 32 位,再追加到载荷 后面。导入时钱包会重算校验和并比对。对演示私钥来说,整个计算过程完全可见:
| 阶段 | 值 |
|---|---|
| 载荷(34 字节) | 800824c314772b2c2859c889471390a36bf66e53a1ca1642f96f0f2c9307a171ca01 |
| SHA256(载荷) | b6020359be4735a8dafe0d76b886c0de8a09ea9459aeba16cb3e3b5473b5d0c2 |
| SHA256(SHA256(载荷)) | 3a0a0417ffa98881ccdd0c7b283639584e0e909389f6bfbbdbac54547d2b732d |
| 校验和(前 4 字节) | 3a0a0417 |
| 送进 Base58 的最终 38 字节 | 800824c314772b2c2859c889471390a36bf66e53a1ca1642f96f0f2c9307a171ca013a0a0417 |
由于校验和只有 32 位,随机损坏蒙混过关的概率是 2−32,约 42.9 亿分之一。这是一个刻意的 取舍:长到足以干掉抄写错误,短到只花 4 个字节。本页把这个机制演示得非常具体 —— 把演示 WIF 改动一个字符, 解码器就会回答「WIF 校验和无效(有笔误或被截断)」,而不是悄悄返回另一把密钥。
Base58Check 防的是意外,不是对手。任何知道你私钥的人都能为任意一个 WIF 重新算出一个 合法校验和。校验和里没有认证、没有加密、也不含任何密钥材料 —— 它只是对公开数据做的一次普通哈希。
3. 载荷:33 字节数据,带标志位则是 34 字节
WIF 的定义就是「对一个以版本字节开头的载荷做 Base58Check 编码」。压缩密钥的载荷长 34 字节,每个字节 各司其职:
| 偏移(载荷内) | 长度 | 字段 | 演示值 | 含义 |
|---|---|---|---|---|
| 0 | 1 字节 | 版本字节 | 80 | 主网私钥(0x80 = 128) |
| 1 – 32 | 32 字节 | 私钥本身 | 0824c31477…07a171ca | 大端序标量,左补零到 32 字节 |
| 33 | 1 字节 | 压缩标志 | 01 | 「由这把密钥推导压缩公钥」 |
| 34 – 37 | 4 字节 | 校验和 | 3a0a0417 | SHA256d(第 0–33 字节) 的前 4 字节 |
| 共 38 字节 | 34 字节载荷 + 4 字节校验和 → 52 个 Base58 字符 | |||
版本字节标识币种与密钥类型,也正是它让最终的字符串一眼就能被认出来:
| 版本字节 | 网络 / 用途 | 得到的 WIF 开头 | 载荷长度 |
|---|---|---|---|
0x80(128) | 比特币主网,非压缩 | 5 | 33 字节 |
0x80(128) | 比特币主网,压缩 | K 或 L | 34 字节 |
0xef(239) | 比特币测试网,非压缩 | 9 | 33 字节 |
0xef(239) | 比特币测试网,压缩 | c | 34 字节 |
0x00(0) | 不是 WIF —— P2PKH 地址版本 | 1(地址) | 21 字节 |
0x05(5) | 不是 WIF —— P2SH 地址版本 | 3(地址) | 21 字节 |
注意最后两行:0x00 和 0x05 是地址版本字节,不是密钥版本字节。整条推导链上
一共会出现三种「像版本号的字节」(0x04 是 SEC1 点标记,0x80 是 WIF 版本,
0x00 是 P2PKH 版本),把它们搞混是这个领域最常见的困惑之一。
4. 为什么压缩 WIF 是 52 个字符、且以 K 或 L 开头
Base58 是大整数编码,输出的长度由数字的大小决定:每个 Base58 字符携带 log258 ≈ 5.858 比特。 38 字节是 304 比特,304 / 5.858 ≈ 51.9,所以最多需要 52 个字符。37 字节是 296 比特, 296 / 5.858 ≈ 50.5,最多 51 个字符。正是这一个字节 —— 压缩标志 —— 把 WIF 从 51 个字符推到了 52 个字符。
首字符的结论更硬。第一个 Base58 位是 floor(值 / 5851),而主网压缩 WIF 的值永远以字节
0x80 开头,因此它落在很窄的区间 [2303, 2303 + 2296)
里。由于 5851 ≈ 2298.757,这个商永远落在约 18.93 到 19.08 之间 ——
而它取整之后只可能是 18 或 19,也就是字母表里 K 与
L 的下标。对主网非压缩 WIF,值落在
[2295, 2295 + 2288),而
5850 ≈ 2292.899,商在约 4.29 到 4.32 之间,取整永远是
4 —— 也就是字符 5。所以首字符不是谁规定的约定,而是算术逼出来的结果。
| 形式 | 载荷 | 参与编码的总字节 | Base58 字符数 | 首字符 | 演示值 |
|---|---|---|---|---|---|
| 压缩(主网) | 34 B | 38 B = 304 比特 | 52 | K 或 L | KwVYL77L…GK5tVqG |
| 非压缩(主网) | 33 B | 37 B = 296 比特 | 51 | 5(永远) | 5HssbguBn…aVNekU |
在本服务器上随机生成 400 把密钥做抽样:184 个 WIF 以 K 开头,216 个以 L 开头,
而且 400 个全部是 52 个字符;同一批密钥的 300 个非压缩 WIF 则全是 51 个字符、全部以 5 开头。
K/L 的分布基本就是掷硬币,因为它取决于随机密钥的高位比特。
5. 为什么 0x01 标志要放在 WIF 里面
2012 年引入压缩密钥时(历史背景见非压缩公钥那一页),钱包面临一个难题: 已有的私钥备份就是一个字符串,钱包必须知道该推导哪一种公钥序列化。如果增加一个独立字段, 所有现成的解析器、印好的纸钱包、生成的二维码都会失效。于是载荷向后扩展了一个可选字节:
- 这个位置本来就是空的。 32 字节密钥是定长的,因此它后面再放一个可选字节毫无歧义:
解码器看到 33 字节载荷就判定「非压缩」,看到 34 字节且末字节是
0x01就判定「压缩」。 - 标志在校验和的覆盖范围内。 它位于被哈希的区域内,因此标志被损坏或被恶意翻转,会像任何 其它笔误一样被检测出来。假如把它放在字符串之外(比如钱包数据库里),它就完全没有任何完整性保护。
- 标志只是提示,不是密钥材料。 它不改变私钥的任何一个比特,只是告诉钱包该对两种公钥编码 中的哪一种做哈希 —— 因而该去看哪个地址。
同一把私钥有两个合法 WIF:演示密钥对应 KwVYL77L…(压缩)与
5HssbguBn…(非压缩)。它们解码出的 32 字节密钥完全相同,地址却不同。两者都谈不上「错」,
只是描述了不同的推导方式。请备份与你的币实际所在地址相匹配的那一个。
6. 钱包如何用这个标志决定从哪里花钱
最后那个分支才是关键。这个标志不仅影响钱包怎么显示你的密钥,它还改变了钱包在链上监控的那个
20 字节哈希,以及日后花费输入时会推入的那把公钥。带压缩标志时,钱包推导 hash160(02/03‖X)、
付款给 146ZNjH7…;不带标志时,推导 hash160(04‖X‖Y)、付款给
16kR3eis…。对同一把密钥而言两个都是正确地址 —— 只是彼此不同的两个地址。
这就是经典故障。老软件(0.6 之前的时代、一些简易清扫工具、一些廉价硬件)要么直接拒绝这个字符串 —— 「无效 WIF」或「长度不对」——要么收下它,却依然推导非压缩地址。如果你的币在压缩地址上,钱包就会 显示余额为零;如果你随后又往它显示的那个地址转币,你的资金就被拆到了两个地址上,而两个不同的钱包可能对 它们各执一词。密码学上什么也没丢 —— 同一把私钥依然同时控制两者 —— 但你现在需要正确的工具才能搬动任一笔 余额。在信任一次导入之前,请先确认钱包显示的地址与你预期的地址一致。
7. 实例演算 —— 每个值都算过并验证过
以下全部是输入框里那个示例私钥的真实输出:
| 项目 | 值 |
|---|---|
| 私钥 k | 0824c314772b2c2859c889471390a36bf66e53a1ca1642f96f0f2c9307a171ca |
载荷 0x80 ‖ k ‖ 0x01 | 800824c314772b2c2859c889471390a36bf66e53a1ca1642f96f0f2c9307a171ca01(34 字节) |
| 校验和 | 3a0a0417 |
| 压缩 WIF | KwVYL77Lcs1ckM39NvGjrtfKhU4KKdR2iB9Wq2FSMN6rbGK5tVqG |
| 长度 / 首字符 | 52 个字符,以 K 开头 |
载荷 0x80 ‖ k | 800824c314772b2c2859c889471390a36bf66e53a1ca1642f96f0f2c9307a171ca(33 字节) |
| 非压缩形式的校验和 | b6f3d7f5 |
| 非压缩 WIF(对照) | 5HssbguBnjbaUVZCsH9YuzUG7T4vYQf51iiodi4izdVy6aVNekU |
| 长度 / 首字符 | 51 个字符,以 5 开头 |
| 它隐含的压缩公钥 | 02ff812e26116a9aa140abe629e7f8a38401653caf925119def59ed3758c67ee80 |
| 它的 hash160 | 21f57b6debcfc5b67182dfb4af1641f0a8189012 |
| 它隐含的 P2PKH 地址 | 146ZNjH7XTXnMd1ofe3z7CL2i8WM7N2UqT |
| 同一把密钥的测试网压缩 WIF | cMrXo27C3vhsunWQmL5sEDAPKhMiz5WinDHywShwrUkrr1RkCJ4i |
注意两种形式的校验和并不相同:3a0a0417 与 b6f3d7f5。追加标志字节改变了哈希输入,
于是也改变了校验和,所以两个字符串的最后四个字符毫无关联。用肉眼比对同一把密钥的两个 WIF 时,
这是一个很有用的判据。
8. 往返验证
一个解不出来的编码毫无价值,所以本页会用 Btc::wifDecode() 解码自己的输出,并在结果面板里
显示恢复出的每个字段:完全相同的 32 字节密钥、已置位的压缩标志、版本字节 80、主网、有效的
校验和,以及原样返回的 34 字节载荷。由于 Base58Check 是双射,往返必然返回原始字节。如果某个工具把
你的 WIF 解码成另一把密钥,那要么是字符串抄错了,要么是工具有缺陷 —— 不存在第三种可能。
9. 压缩 WIF 与非压缩 WIF 对照
| 压缩 WIF | 非压缩 WIF | |
|---|---|---|
| 载荷 | 0x80 ‖ k ‖ 0x01(34 B) | 0x80 ‖ k(33 B) |
| 参与编码的总字节 | 38 B | 37 B |
| 字符串长度 | 52 个字符 | 51 个字符 |
| 首字符(主网) | K 或 L | 5 |
| 首字符(测试网) | c | 9 |
| 校验和(演示密钥) | 3a0a0417 | b6f3d7f5 |
| 隐含的公钥 | 33 字节,02/03‖X | 65 字节,04‖X‖Y |
| 隐含的地址(演示密钥) | 146ZNjH7…2UqT | 16kR3eis…WG2G |
| 能否用于 SegWit / Taproot | 可以 | 不能 |
| 花费时的手续费 | 约 107 字节 scriptSig | 约 139 字节 scriptSig |
| 典型来源 | 2012 年以来的所有钱包 | 纸钱包与 2012 年前的软件 |
镜像的另一半请看私钥 → 非压缩 WIF;想判断别人给你的字符串属于哪一种, 请看 WIF → 私钥 HEX。
10. 安全须知
- WIF 就是明文私钥。 Base58 是编码,不是加密,也不是混淆。任何看到这个字符串的人都能 立刻、不可逆地花掉那些币。
- 校验和防意外,不防攻击。 它无法告诉你某个 WIF 是你自己生成的还是别人给你的, 也拦不住任何人为自己挑选的密钥重新算出一个合法校验和。
- 小心粘贴的地方。 WIF 字符串是钓鱼网站、剪贴板木马和聊天诈骗的标准猎物。纸钱包上的 私钥应该被输入到你自己掌控的软件里(最好离线),而不是任何你无法掌控的网页表单。
- WIF 是一把密钥,不是一个钱包。 把它导入现代 HD 钱包,只会建立一个个独立、 不参与派生的账户:没有助记词、没有 xpub、没有找零地址,除非钱包专门管理「导入型」密钥, 否则也不会生成 SegWit 或 Taproot 地址。若要清扫,请把余额全部扫到一把你真正做过备份的密钥上。
- 本页会把你的密钥发到服务器。 请求就是一次普通的 HTTP GET,所以请把这里的一切测试都 当成公开行为:使用演示密钥或其它一次性密钥,绝不要使用保护真实资金的密钥。
11. 常见错误
- 「Base58 能藏住我的私钥。」 藏不住。它是一个无损变换,任何解码器都能在微秒级还原。
- 把
0x01标志当成密钥的一部分。 密钥是 32 字节,标志是元数据。把标志一起 留下的解码器会得到一把 33 字节的「私钥」,那是无效的。 - 混淆版本字节。
0x80是 WIF,0x00是 P2PKH 地址,0x04是非压缩公钥标记。同样的字节位置,三种毫不相干的含义。 - 以为同一把密钥的
5…WIF 与K…WIF 会给出同一个地址。 永远不会 —— 这正是那个标志存在的全部意义。 - 手工改最后四个字符。 那是校验和;字符串里任何内容一变,它就必须重算。 把它覆盖掉,正是人们「弄丢」本来完好的密钥的方式。
- 把 WIF 当成种子短语。 它编码的是某个派生位置上的一把密钥,无法生成一族地址, 也不是 BIP39 助记词。
12. 速查表
| 项目 | 值 |
|---|---|
| 编码方式 | Base58Check:载荷 ‖ SHA256d(载荷) 的前 4 字节 |
| 压缩载荷 | 0x80 ‖ k(32 B) ‖ 0x01 |
| 载荷 / 编码长度 | 34 B / 38 B |
| 输出长度 | 52 个 Base58 字符 |
| 首字符(主网压缩) | K 或 L |
| 校验和大小 / 强度 | 4 字节 / 实践中能抓住所有单字符笔误(约 232 分之一漏网) |
| Base58 字母表大小 | 58(不含 0、O、I、l) |
| 标志的含义 | 推导 33 字节的压缩公钥 |
| 隐含的地址 | 由 hash160(02/03‖X) 得到的 P2PKH |
| 可逆吗 | 可以 —— 解码能精确还原 k |