Private Key Tools

私钥 → 非压缩公钥

在 secp256k1 上计算 P = k·G,并把该点序列化成最初的 65 字节形式 04‖X‖Y —— 2012 年之前生成的每一把密钥都用这种编码,也只有它能复现老式非压缩地址与 5… 开头的 WIF。

64 位十六进制 = 32 字节。允许 0x 前缀、空格与大写字母,不足 64 位会自动左补 0。数值必须落在 [1, n−1] 内。本页不会记录你的私钥,但它确实会被发送到服务器 —— 做实验时请使用测试密钥。
还没有输入

请在上方输入内容后点击「转换」。不知道填什么?点「填入示例」即可载入占位符里的演示数据。

技术原理详解

本页计算了什么

你输入一个 256 位的私钥 k,本页给出它的非压缩公钥: 把椭圆曲线上的点 P = k·G 完整写出来 —— 两个坐标一个不少,前面加一个 04 字节作为标记。 总共 65 字节,这正是中本聪最初的客户端为每一把密钥使用的格式。

P = k · G   →   公钥 = 0x04 ‖ X ‖ Y  (65 字节 = 520 位)
私钥 k→ k · G→ 点 (X, Y)→ 04 ‖ X ‖ Y→ SHA-256→ RIPEMD-160→ hash160→ 1… 地址

这里没有任何新的密码学。曲线上的运算与「压缩公钥」那一页完全一样, 不同的只是把结果序列化的方式 —— 而正是这个差别,让同一把私钥拥有两个彼此无关的地址。

1. 为什么非压缩形式正好是 65 字节

公钥是 secp256k1 上的一个点:两个落在 [0, p−1] 区间、满足 Y² ≡ X³ + 7 (mod p) 的数 X 和 Y,其中 p = 0xFFFFFFFF…FFFFFC2F(256 位)。既然每个坐标都小于 p,那么每个坐标都能装进 32 字节。编码方式也就是最直白的那种 —— 先来一个字节声明「下面是一个非压缩形式的点」, 再跟上两个坐标:

偏移(字节)长度字段说明
01类型标记 / 前缀04 = 非压缩点
132X 坐标,大端序,左补零P = k·G 的第一个坐标
3332Y 坐标,大端序,左补零P 的第二个坐标
合计 65 字节520 位 → 130 位十六进制

有三个细节很容易出错:

2. 前缀字节:04,以及被废弃的 06/07

第一个字节来自 SEC1 —— 定义椭圆曲线点如何写成字节串的那份标准。SEC1 给每种点编码 分配了一个字节的标识,比特币把这些标识全都继承了下来:

前缀名称结构长度今天的状况
00无穷远点—1 字节永远不能作为公钥;k = 0 才会得到它
02压缩,Y 为偶02 ‖ X33 字节现代标准形式
03压缩,Y 为奇03 ‖ X33 字节现代标准形式
04非压缩04 ‖ X ‖ Y65 字节历史遗留,但在旧脚本里完全合法
06混合,Y 为偶06 ‖ X ‖ Y65 字节已淘汰;奇偶位是冗余的
07混合,Y 为奇07 ‖ X ‖ Y65 字节已淘汰;奇偶位是冗余的
无x-only(BIP340 / Taproot)X32 字节仅 Taproot 使用现代形式

混合(hybrid)形式 06 和 07 把 Y 的奇偶性 塞进标记的最低位(06 为偶、07 为奇),同时又老老实实把 Y 完整写了一遍。 于是那个奇偶位没有提供任何 Y 字节尚未提供的信息,反而给了攻击者第二个可篡改的冗余字段: 把标记一翻,就得到一个自相矛盾的密钥。SEC1 后来的修订版正是出于这个理由删掉了混合编码,也从没有哪个钱包 生成过它们,链上几乎没有实际使用量。本站的解析器仍然接受 06/07 开头的密钥, 是为了让你能亲眼看看它们长什么样 —— 但绝不要自己生成或保存这种密钥。

它和「网络字节」毫无关系

这里的 04 是点的标记。它与地址的版本字节(主网 P2PKH 是 0x00)、 以及 WIF 的版本字节(0x80)都不是一回事。同一条推导链上会出现三种不同的「前缀字节」, 把它们混为一谈是经典的入门错误。

3. 这个格式从哪来 —— 以及为什么 2012 年改了

2009 年的原始比特币客户端通过 OpenSSL 生成密钥,而 OpenSSL 对 EC 点的默认字节串编码就是非压缩的。 因此比特币头三年里所有软件创建的密钥都是 65 字节的 04‖X‖Y,早期区块链上的每个 地址都是这 65 字节的 hash160。这是历史默认值,不是谁手动打开的某个「遗留模式」。

压缩是后来作为节省空间的优化被提出来的。一个点的 Y 坐标完全由 X 加上一个比特 (奇偶性)决定,所以 65 字节里有 32 字节是冗余的。一份 BIP 式的提案把这次改动梳理清楚, 2012 年 3 月发布的 Bitcoin 0.6.0 正式支持压缩公钥,并把它作为新生成密钥的默认形式。 动机纯粹是经济与工程上的:

由于这次改动改变的是被哈希的字节,钱包必须告诉用户某把密钥属于哪种形式 —— 而裸私钥本身不携带这个信息。 这正是 WIF 格式在同一次发布中增加 0x01 压缩标志的全部原因(见 私钥 → 压缩 WIF)。关键在于:这次改动是增加了一种格式,而不是让旧格式失效。 2012 年躺在非压缩地址上的币,今天依然可以在同样的共识规则下花掉。

4. 为什么非压缩形式今天仍然重要

非压缩形式不被允许的地方

SegWit witness v0 的规则要求公钥必须是压缩的:P2WPKH 与 P2SH-P2WPKH 输出只能用 33 字节公钥花费。 现代那些基于 descriptor 的钱包也一样,很多在导入时就直接拒绝非压缩密钥。所以非压缩密钥只能通向 P2PKH(以及历史上的裸 P2PK)脚本 —— 你无法把它变成 bc1q… 地址。

5. 用真实演示数据演算一遍

下表全部是本页对输入框里那个示例私钥实际算出的值。点一下「填入示例」就能复现:

步骤值
私钥 k(十六进制)0824c314772b2c2859c889471390a36bf66e53a1ca1642f96f0f2c9307a171ca
私钥(十进制)3683455675284633286911943861444039993120875154046227415438637967083965608394
P = k·G 的 Xff812e26116a9aa140abe629e7f8a38401653caf925119def59ed3758c67ee80
P 的 Y8f49cde13c7ffd64f1d730bf87a743a578eda4971ddac4a08118160732b424ae
Y 的奇偶性末位十六进制是 e → 偶数(所以这把密钥的压缩兄弟以 02 开头)
非压缩公钥(本页输出)04ff812e26116a9aa140abe629e7f8a38401653caf925119def59ed3758c67ee808f49cde13c7ffd64f1d730bf87a743a578eda4971ddac4a08118160732b424ae
它的长度65 字节 = 130 位十六进制 = 520 位
对这 65 字节做 hash1603f0e966dc089c611a9c1d03bd4f69ea53b0223f9
由它得到的 P2PKH 地址16kR3eiswUY6tmGnxZhwQmW6LAvTLGWG2G
对照:压缩公钥02ff812e26116a9aa140abe629e7f8a38401653caf925119def59ed3758c67ee80
对照:它的 hash16021f57b6debcfc5b67182dfb4af1641f0a8189012
对照:它的 P2PKH 地址146ZNjH7XTXnMd1ofe3z7CL2i8WM7N2UqT

最后三行才是本页的重点。同一个 256 位数字 k 同时对应 16kR3eis…GWG2G 和 146ZNjH7…2UqT。它们不是别名:它们是两个不同的 20 字节承诺值、 两个不同的地址,而钱包通常只盯着其中一个。

地址本身是一个用上面的 hash160 构造出来的 Base58Check 结构:

地址组成部分长度演示值
版本字节1 字节00
hash160 载荷20 字节3f0e966dc089c611a9c1d03bd4f69ea53b0223f9
校验和 = SHA256d(载荷) 的前 4 字节4 字节3b0b7cbd
编码结果34 个 Base58 字符16kR3eiswUY6tmGnxZhwQmW6LAvTLGWG2G

6. 压缩与非压缩对照表

非压缩压缩
序列化04 ‖ X ‖ Y02/03 ‖ X
字节 / hex 位数 / 比特65 / 130 / 52033 / 66 / 264
携带的信息两个坐标X 加上 Y 的奇偶性
hash160 的输入全部 65 字节全部 33 字节
同一把密钥的 P2PKH 地址16kR3eis…GWG2G146ZNjH7…2UqT
对应 WIF 前缀5…K…/L…
花费时推入的公钥字节数6533
典型 P2PKH scriptSig 大小1 + 72 + 1 + 65 = 139 字节1 + 72 + 1 + 33 = 107 字节
能否用于 witness v0 / Taproot不能witness v0 可以(Taproot 用 x-only)
从何时成为默认Bitcoin 0.1(2009)Bitcoin 0.6.0(2012 年 3 月)
今天是否仍然合法是,在旧式脚本类型中是

那个 scriptSig 的算式值得展开说明:花费 P2PKH 要推入一个 DER 签名加上 1 字节 sighash 类型(约 72 字节) 和一个公钥,每个前面还有一个长度字节。在按虚拟字节计费的手续费体系下,那 32 字节的差额会在每一个输入上、 永远地付出去。

7. 一把私钥、两个地址 —— 最经典的「我的币丢了」

私钥并不知道自己被怎么编码

数字 k 就只是一个数字。「压缩」还是「非压缩」是序列化的属性,而在钱包备份里, 记录这个选择的唯一地方就是 WIF 字符串中的一个标志字节。把一把非压缩私钥导入一个默认压缩的钱包, 它会推导 hash160(02/03‖X)、去查 146ZNjH7…、什么也找不到,然后显示余额为零 —— 而你的币其实安安稳稳地躺在 16kR3eis… 上。什么也没丢,但看起来和丢了没有区别, 而这就是这类故事里最常见的一种。

有三点值得记住:

  1. 两个地址都由你控制。 同一把私钥同时掌管压缩地址和非压缩地址。如果很久以前有人往旧地址 给你打过钱,那些币今天仍然可以动。
  2. 它们无法合并。 你没法把非压缩地址「转换」成压缩地址;只能发一笔普通交易,把币从前者 转到后者,并支付手续费。
  3. 下结论前先两种都查。 当恢复出来的钱包显示为零时,把两种形式都算出来(本页与 它的压缩孪生页做的正是这件事),再到链上分别搜索这两个地址。

8. 这一步之后会发生什么

65 字节公钥→ SHA-256→ RIPEMD-160→ 20 字节 hash160→ Base58Check(0x00 ‖ hash160)→ 1… 地址

9. 安全须知

10. 常见错误

11. 速查表

项目值
公式secp256k1 上的 P = k·G
编码0x04 ‖ X(32) ‖ Y(32)
长度65 字节 / 130 位十六进制 / 520 位
前缀含义02/03 压缩,04 非压缩,06/07 混合(已淘汰)
坐标大端序、定长 32 字节、对 p 取模
前缀在哪里起作用在 hash160 的预映像里 —— 它会改变地址
可导出的地址类型仅 P2PKH(1…)与历史上的裸 P2PK
配套的备份格式以 5 开头、51 个字符的 WIF
能反推出 k 吗不能(ECDLP)
链上仍然有效吗在旧式脚本类型中有效