安全实用 本地计算 开箱即用 内置示例 不留痕迹

Base58 在线编码解码

Base58 是为「人手抄写」设计的编码:从 Base64 的字母表里剔掉 0/O、I/l 这几组容易看错的字符,剩下 58 个。比特币钱包地址、部分区块链项目的密钥与短码都用它。本工具按 Bitcoin 口径正确处理前导零字节,并额外给出十六进制视图,方便核对二进制数据。

比特币地址抄给朋友时,没有人希望里面出现「这是数字 0 还是字母 O」的争执——Base58 就是为抄写和口述设计的编码,把最容易混淆的几个字符从字母表里剔掉了。粘贴文本或十六进制数据即可编码,解码会同时给出文本与十六进制两种视图,前导零也按比特币口径妥善处理。

两个容易踩的口径:一是前导零——纯数值换算会丢掉开头的零字节,Bitcoin 规定每个前导零字节编码成一个 1,漏了这条,以 1 开头的地址解码后字节数就不对;二是 Base58 本身没有校验能力,抄错了不报错,比特币地址靠的是外层 Base58Check 的 4 字节校验和。它同样不是加密。

使用步骤

  1. 选方向:文本转 Base58,或 Base58 转文本。
  2. 粘贴内容;解码时自动忽略空格与换行,分组抄写的串可直接粘。
  3. 解码结果不是文本时看十六进制视图与字节数(私钥、哈希属正常现象)。
  4. 出现 0、O、I、l 直接报错——Base58 里没有这四个字符,必是抄错。

计算原理与示例

前导零字节为什么要转成字符 1

Base58 的运算是「把字节串当成一个大整数,反复除以 58 取余数」,但纯数值换算会丢掉开头的零字节——因为数值上 0x00 与「没有这个字节」是一样的。Bitcoin 的规定是把每一个前导零字节编码成一个字符 1,解码时再把开头的 1 还原成零字节。如果漏掉这一步,以 0x00 开头的地址(版本字节就是 0x00 的那一类,最典型的是以 1 开头的地址)解码后会少字节。本工具在编码与解码两侧都实现了这条规则。

解码结果没有文本只有十六进制

解码方向的输入不一定是文本。比如 Base58 形式的私钥、哈希值、二进制密钥片段,按 UTF-8 解释时可能根本无法对应到合法字符。这种情况下主结果会留空并标注「非文本」,同时给出十六进制结果与字节数——十六进制才是这类数据的正确呈现方式,不是工具出错。

Base58 与 Base64 的取舍

Base58 相比 Base64 少了 6 个字符(58 对 64),换来的是「一眼能分清 0 与 O、1 与 l」。代价是同样的数据体积大约多 4~5%,而且不含校验能力——Base58 本身不检测抄错,比特币地址另外用 Base58Check 加了 4 字节校验和。所以地址抄错时是否会报错,取决于目标系统是否用了 Base58Check,与本工具无关。

代码示例

JavaScript Node 用 bs58 库

// npm install bs58
const bs58 = require("bs58");

bs58.encode(Buffer.from("hello"));   // 编码
bs58.decode("Cn8eVZg");              // 解码,返回 Buffer

// 比特币地址用的是 Base58Check(带 4 字节校验和),
// 需要额外计算双 SHA-256 校验段,bs58 不含这一层

Python base58 库

# pip install base58
import base58

base58.b58encode(b"hello")
base58.b58decode(b"Cn8eVZg")

# 前导零字节按 Bitcoin 口径转成字符 1,库已处理

常见问题

Base58 和 Base64 到底有什么区别?

Base64 用 64 个符号(大小写字母、数字加 + 和 /),每 6 位放一个字符,体积只比原文大三分之一;Base58 用 58 个符号,剔掉了 0、O、I、l 这四个(加两个符号位)容易看错的字符,每 8 位对数运算一次,体积大约大 37%。简单说:Base64 紧凑、适合机器传输;Base58 好认、适合人手抄写和口头传达。

为什么 Base58 的字符里看不到 0、大写 O、大写 I 和小写 l?

这四个字符在人手抄写时最容易混淆:0 与 O 长得几乎一样,1、I、l 三者也常常分不清。比特币的早期设计者把它们从字母表里去掉了,剩下的就是 58 个字符。所以 Base58 串里出现 0 或 O,可以立即判定是抄错了。

为什么比特币地址经常以 1 开头?

老式比特币地址(P2PKH)的第一个字节是版本号 0x00,按 Bitcoin 口径每个前导零字节编码成一个字符 1,所以这类地址必然以 1 开头,能开头的 1 有几个取决于后面还跟了几个零字节。这也解释了为什么解码这段地址时开头要还原出零字节——少还原就会字节数不对,进而地址校验失败。

编码出来的是不是可以当加密串用?

不可以。Base58 和 Base32、Base64 一样只是换一种写法,没有密钥、不提供任何保密性,任何人拿到串都能一键还原。它的价值在于「少出错、好抄写」,不是「藏内容」。需要保密请用加密算法(如本工具的 AES 加密),并且无论如何不要把真实私钥贴到任何在线工具里。

同一段文本每次编码结果都一样,而 AES 加密却不一样,为什么?

因为两者的目标不同。编码是确定性映射:同样的输入必然得到同样的输出,这样才能在另一端还原。AES 加密会每次生成随机的盐与初始向量,同一明文同一口令两次加密的结果必然不同——这是刻意的,避免攻击者通过「密文相同」推断出「明文相同」,也让彩虹表失效。

解码后主结果是空的,只显示了十六进制,是坏了吗?

不是。这说明这段 Base58 还原出来的字节不是合法的 UTF-8 文本(例如私钥、哈希、压缩后的数据),无法当作文字显示。工具会识别这种情况并标注「非文本」,保留完整的十六进制结果与字节数——核对二进制数据时请以十六进制为准。

为什么我把地址解出来的字节数比想象的多?

常见的两个原因:一是前导零字节被还原了,它们本来就存在,只是编码时被压成了字符 1;二是完整的 Base58Check 地址末尾还带 4 个字节的校验和,解码自然会多出来。想确认版本字节与校验和是否正确,建议用支持 Base58Check 的专用工具。

输入里带空格或换行会影响解码吗?

不会。解码时会自动忽略所有空白字符与换行,所以按每 8 个字符分组、手动抄下来的串可以直接粘贴。但字母表以外的可见字符(比如 0、O、I、l)会导致报错并提示非法字符,这是刻意设计的——Base58 里出现这些字符一定是抄写有误,静默忽略反而会输出错误结果。

延伸阅读

来自本站原创文章,讲清这个工具背后的算法与口径。