Base58Check 编码 / 解码
把任意 1…、3…、5…、K… 字符串拆开:版本字节、载荷主体、4 字节双 SHA256 校验和,以及它究竟能不能通过校验。也可以反过来 —— 给它一个十六进制载荷,返回带校验和的 Base58Check 字符串。
请在上方输入内容后点击「转换」。不知道填什么?点「填入示例」即可载入占位符里的演示数据。
本页做什么
比特币里所有 1…、3…、m…、2…、5…、
K… 字符串背后都是 Base58Check。它就是一次进制转换,外挂一个校验和:
解码模式接收一个成品字符串,把它拆开:版本字节、载荷主体、校验和,以及校验和是否真的通过。 编码模式接收一个十六进制载荷,返回对应的 Base58Check 字符串,并显示它追加的校验和。
1. Base58 字母表,以及为什么少了四个字符
Base58 不是任何标准。它就是 Base64 去掉碍事的符号,再拿掉六个容易抄错的字符。比特币使用的字母表是:
| 下标 | 字符 | 数量 |
|---|---|---|
| 0 – 8 | 123456789 | 9 个数字 |
| 9 – 32 | ABCDEFGHJKLMNPQRSTUVWXYZ | 24 个大写字母 |
| 33 – 57 | abcdefghijkmnopqrstuvwxyz | 25 个小写字母 |
| 合计 | 58 个字符 | |
Base64 舍弃了 + 和 /,因为它们会破坏复制粘贴与 URL 处理。比特币版本又刻意多去掉了四个:
| 被去掉 | 原因 |
|---|---|
0(数字零) | 在大多数字体里和 O 几乎一样,也容易与小写 o 混淆 |
O(大写 O) | 同一个问题的另一面 |
I(大写 i) | 在无衬线与等宽字体中与小写 l 完全相同 |
l(小写 L) | 在很多字体里与数字 1 完全相同 |
注意哪些留下了:小写 i 和小写 o 都在字母表里。规则并不是「不要形近字母」,
而是「绝不留下会互相混淆的两个字符」:1 之所以保留,是因为它现在是唯一的竖线字形;
i、o 之所以保留,是因为与它们形近的那两个才是被删掉的。收益是:抄错的地址更可能
被校验和拦住,而不是悄悄变成一个合法但错误的地址。
2. 前导 1 的约定
进制转换就是把一个数变成一串数字。它无法表达前导零字节,因为前导零不携带任何数值信息:
0x0021 与 0x21 是同一个数。因此比特币另立了一条明确规则:
1,然后才是剩余数字的 58 进制表示| Base58 字符串 | 解码后的字节 | 说明 |
|---|---|---|
1 | 00 | 一个零字节,没有数值部分 |
11 | 0000 | 两个零字节 |
12 | 0001 | 一个零字节,然后是数值 1 |
z | 39 | 没有前导零;z 下标是 57 —— 一位字符能表示的最大值 |
这就是主网 P2PKH 地址以 1 开头的原因:它的载荷第一个字节是版本字节 0x00,于是产生
一个字面字符 1,而它不属于进制转换出来的数字。同样地,25 字节的 P2PKH 地址永远是 34 个
字符:1 个 1 给版本字节,剩下 24 字节大约需要 33 个字符。
用一个极端例子就能直接看到这条规则:载荷 0x00 后面跟二十个零字节,编码结果是
1111111111111111111114oLvT2 —— 21 个前导 1,每个零字节一个,后面 4 个普通
base58 字符代表那 4 字节校验和。
3. 校验和:能查出什么,不能做什么
编码前会在载荷后追加 4 字节双 SHA-256,任何解码器都会重新算一遍:
| 错误 | 能否查出 | 原因 |
|---|---|---|
| 单个字符打错 | 能,概率 1 − 2−32 | 载荷变了,重算的校验和就变了;只有约四十亿分之一的巧合会通过 |
| 两个及以上字符打错 | 同样概率 | 这里不对错误形态做任何假设,所以保证是概率性的,不是绝对的 |
| 字符顺序颠倒 | 同样概率 | 与某些基于编码的校验和不同,Base58 的顺序敏感性来自数值本身,而不是逐位相加 |
出现非法字符(0、O、I、l) | 必然查出 | 这些字符压根不在字母表里,解码直接失败 |
| 字符串被截断 | 通常能 —— 或者直接报「太短」 | 解码不足 5 字节时,连 4 字节校验和都装不下 |
| 一个指向别的地址的合法字符串 | 查不出 | 校验和防的是手误,永远防不了被另一个格式正确的字符串替换 |
校验和失败时,你得到的全部信息就是:这个字符串是错的。校验和是哈希,是一个看起来随机
的 4 字节摘要,没有任何代数结构 —— 因此无法从「期望 cbd7667e、实得 cbd76695」
反推出「第 27 个字符可疑」。唯一正确的做法是重新复制或重新扫描原字符串。靠猜就是丢币的开始;BIP173 也正是
因此指出,Base58Check 这类设计「没有任何错误检测保证」,只有很小的随机碰撞概率。
作为对照,bech32 地址做了相反的设计选择:它的 BCH 校验和保证能检测任何影响至多 4 个字符的错误, 甚至还能算出一小组候选错误位置 —— 见 Bech32 / Bech32m。
4. 版本字节:载荷的第一个字节就是类型标签
除校验和之外的一切都是不透明字节;它们的含义完全来自版本字节,也就是载荷的第一个字节。本页支持 六种:
| 版本字节 | 含义 | 载荷长度(不含校验和) | 开头字符 |
|---|---|---|---|
0x00 | P2PKH 地址,主网 | 21 字节(1 + hash160) | 1 |
0x05 | P2SH 地址,主网 | 21 字节(1 + 脚本哈希) | 3 |
0x6F | P2PKH 地址,测试网 | 21 字节 | m 或 n |
0xC4 | P2SH 地址,测试网 | 21 字节 | 2 |
0x80 | WIF 私钥,主网 | 33 字节(非压缩)或 34 字节(压缩,末尾 0x01) | 5,或 K / L |
0xEF | WIF 私钥,测试网 | 33 或 34 字节 | 9 或 c |
有两点值得记牢。第一,首字符不是被选出来的,而是版本字节与载荷长度共同导致的结果;所以「以
1 开头的地址」与「版本字节 0x00」说的完全是同一件事。第二,版本字节没有任何东西
为它背书:一个字符串要么自洽、要么不自洽,但没人拦得住你把一个格式正确的测试网地址称作主网地址。同时支持
两个网络的钱包必须自己校验版本字节。
5. 需要多少字符?58N 的算术
每个 Base58 字符携带 log2(58) ≈ 5.858 位,因此每个字节大约需要 1.3657 个字符:
| 字节数(载荷 + 4 字节校验和) | 位数 | log58(2位数) | 字符数 | 示例 |
|---|---|---|---|---|
| 25 字节 | 200 | 34.141 | 34,最多 35 | 146ZNjH7XTXnMd1ofe3z7CL2i8WM7N2UqT(34) |
| 37 字节 | 296 | 50.529 | 51 | 5HssbguBnjbaUVZCsH9YuzUG7T4vYQf51iiodi4izdVy6aVNekU(51) |
| 38 字节 | 304 | 51.895 | 52 | KwVYL77Lcs1ckM39NvGjrtfKhU4KKdR2iB9Wq2FSMN6rbGK5tVqG(52) |
作为参考,5833 = 15599970876632771988160814054146447252125923204784443097088,
5834 = 904798310844700775313327215140493940623303545877497699631104;而 2192 =
6277101735386680763835789423207666416102355444464034512896,2200 =
1606938044258990275541962092341162602522202993782792835301376。由于 2192 <
5834,24 字节永远装得进 34 个字符 ——
这就是 P2PKH 地址里那个 1 加上 33 个字符。
那地址有没有可能变成 35 个字符?从算术上说可以:当 25 字节载荷的数值达到 5834 时就需要第 35
个字符,而这要求首字节不小于 0x90。上表里的每个版本字节都远低于此,所以真实的比特币
1…、3… 地址永远是 34 个字符。(这里实测过:载荷以 0x8F 开头得到 34 个
字符,以 0x90 开头则得到 35 个。)
6. Base58、Base58Check、Bech32 对比
| Base58Check | Bech32(v0) | Bech32m(v1+) | |
|---|---|---|---|
| 字母表 | 58 个字符,大小写混合 | 32 个字符,仅小写 | 32 个字符,仅小写 |
| 校验和 | 双 SHA-256 的 4 字节 | 6 个字符,BCH 码,常量 1 | 6 个字符,BCH 码,常量 0x2bc830a3 |
| 错误检测 | 概率性(1 − 2−32) | 保证检测 ≤ 4 个错误字符 | 保证检测 ≤ 4 个错误字符 |
| 类型标签 | 载荷内部的版本字节 | 数据部分的第一个值 = witness 版本 | 数据部分的第一个值 = witness 版本 |
| 大小写 | 区分大小写,两种都合法 | 禁止大小写混用 | 禁止大小写混用 |
| 用途 | P2PKH、P2SH、WIF | P2WPKH、P2WSH | P2TR 及未来版本 |
7. 实例演算:解码示例 P2PKH 地址
下表就是 146ZNjH7XTXnMd1ofe3z7CL2i8WM7N2UqT 的真实结构,与解码模式的输出完全一致:
| 步骤 | 值 |
|---|---|
| Base58 字符串 | 146ZNjH7XTXnMd1ofe3z7CL2i8WM7N2UqT(34 个字符) |
| 解码后的字节(载荷 ‖ 校验和) | 0021f57b6debcfc5b67182dfb4af1641f0a8189012cbd7667e(25 字节) |
| 载荷 | 0021f57b6debcfc5b67182dfb4af1641f0a8189012(21 字节) |
| 版本字节 | 00 → P2PKH,主网 |
| 载荷主体 | 21f57b6debcfc5b67182dfb4af1641f0a8189012(20 字节 = 一个 hash160) |
| 载荷的 SHA-256 | 705cbbd9867cfeb7d5b0356c9bafe09bb2a50c40e69c7ee0535cfcbf987db587 |
| 载荷的双 SHA-256 | cbd7667ea989f5994e7e12439589085e0eda7572712b71cf66374edff592182f |
| 校验和(字符串最后 4 字节) | cbd7667e —— 与上面的前 4 字节一致,校验通过 |
| 解读 | P2PKH,主网,支付给 hash160 21f57b6d…89012 |
P2SH 地址形状完全相同,只是版本字节不同:3DZT76KyKyc5zkzvLugP8umgt4RPY4XPQw 解码得到载荷
05823333d5fd23a83661e8e47629552c4a5bfc8b6e(版本 05,校验和 acbfef44),
其中那 20 字节主体是某个 redeemScript 的哈希,而不是公钥的哈希。
8. 实例演算:解码示例 WIF
| 步骤 | 值 |
|---|---|
| Base58 字符串 | KwVYL77Lcs1ckM39NvGjrtfKhU4KKdR2iB9Wq2FSMN6rbGK5tVqG(52 个字符) |
| 解码后的字节 | 800824c314772b2c2859c889471390a36bf66e53a1ca1642f96f0f2c9307a171ca013a0a0417(38 字节) |
| 载荷 | 800824c314772b2c2859c889471390a36bf66e53a1ca1642f96f0f2c9307a171ca01(34 字节) |
| 版本字节 | 80 → WIF,主网 |
| 载荷主体 | 0824c314…a171ca(32 字节私钥)后面跟着 01 |
末尾那个 01 | 「压缩公钥」标志 —— 正是它的存在让这个地址族产生 K…/L… 形式的 WIF |
| 双 SHA-256 校验和 | 3a0a0417ffa98881ccdd0c7b283639584e0e909389f6bfbbdbac54547d2b732d → 前 4 字节 3a0a0417,与字符串一致 |
| 对照 | 5HssbguBnjbaUVZCsH9YuzUG7T4vYQf51iiodi4izdVy6aVNekU 是 51 个字符:版本字节相同,但没有末尾标志,因此对应非压缩公钥 |
不看那个 01 标志,你就无法判断这把私钥控制哪一个地址 —— 而这正是人们「弄丢」其实还在自己手里的
币的最常见原因。这个标志存在编码后的字符串里,不在私钥里。
9. 实例演算:编码
编码模式输入载荷 00751e76e8199196d454941c45d1b3a323f1433bd6(BIP173 标准测试用的 hash160,
版本字节 00),得到:
| 步骤 | 值 |
|---|---|
| 载荷 | 00751e76e8199196d454941c45d1b3a323f1433bd6(21 字节) |
| 双 SHA-256 | 510d1634d943109b69da527ef5948106f22b655fb5193b4e9ef7e4dcd342d245 |
| 追加的校验和 | 510d1634 |
| 参与进制转换的字节 | 00751e76e8199196d454941c45d1b3a323f1433bd6510d1634(25 字节) |
| Base58Check 结果 | 1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH(34 个字符) |
把结果再送进解码模式,会还原出原来的 21 字节载荷并且校验通过 —— 这正是这种编码的意义:字符串自己带着 完整性证明。
10. 安全须知与常见错误
- 绝不要手动「修」一个校验失败的字符串。 校验和已经说了不行;没有东西可修,也没有办法 找出是哪个字符错了。
- 校验通过不等于可信。 如果攻击者能把你的地址换成他自己那个格式正确的地址,那它就能通过 世界上所有的校验和。地址的来源必须在线下另行核实。
- 大小写是有意义的。 Base58 同时包含大小写,所以
146znjh7…和146ZNjH7…是两个不同的字符串(而且前者几乎肯定校验失败)。bech32 干脆禁止混用大小写; Base58 只是把它当成不同的数据。 - 版本字节不是网络认证。 字符串里没有任何东西声称「这是主网」;那个字节只让字符串自洽。
- 别指望 WIF 的载荷长得像地址。 34 字节的载荷是一把密钥加一个标志。把它喂给地址解码器只会 得到一串无意义的东西,而不是一个钱包。
本页会解码你粘贴的任何 Base58Check 字符串,包括私钥。任何见过这个字符串的人都拥有那些币。如果一个 「捡到的」或「泄漏的」WIF 是真的,那么在你看到它的那一刻,余额就已经没了。
11. 它在链条中的位置
- 上游: hash160 → P2PKH / P2SH / P2WPKH 地址 产生放进载荷里的 那 20 字节主体;私钥 → P2PKH 地址 与 私钥 → 压缩 WIF 则直接给出成品字符串。
- 下游: Bech32 / Bech32m 解码 处理另一种地址编码; WIF → 私钥 HEX 在 WIF 上比本页的解码模式再往前走一步。
12. 速查表
| 项目 | 值 |
|---|---|
| 字母表 | 123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz |
| 被排除的字符 | 0、O、I、l |
| 每字符位数 | log2(58) ≈ 5.858 |
| 校验和 | SHA256(SHA256(载荷)) 的前 4 字节 |
| 校验和空间 | 232 = 4294967296 种 |
| 前导零字节 | 每个 0x00 字节对应一个字面字符 1 |
| P2PKH / P2SH 地址长度 | 恒为 34 个字符 |
| WIF 长度 | 非压缩 51 个字符,压缩 52 个字符 |
| 能纠错吗 | 不能 —— 只能检测 |