Private Key Tools

十进制私钥 → HEX、WIF 与地址

按人类书写数字的方式输入私钥 —— 一个大整数 —— 本页把它转换成规范的 256 位 HEX 形式,再推导出两种 WIF、两种公钥、两个 hash160 以及全部十个地址。空格、逗号与下划线会被忽略。

只需要数字;空格、逗号、下划线会先被去掉(3 683 455… = 3,683,455… = 3683455…)。数值必须落在 [1, n−1],其中 n = 115792089237316195423570985008687907852837564279074904382605163141518161494337,因此最多 78 位。
还没有输入

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

技术原理详解

本页计算了什么

本页接受按人类习惯写出来的私钥 —— 一个普通的十进制整数 —— 把它转换成规范的 256 位十六进制形式, 然后沿着整条推导链算下去。转换前会先去掉空格、逗号和下划线,因为 3 683 455 675 …、3,683,455,675… 和 3683455675… 是同一个数字 —— 分隔符是给人看的,不是给计算机看的。

khex = base10→base16( kdec )   然后   P = k · G
十进制整数→ 去除分隔符→ 进制转换→ 32 字节 hex(左补零)→ WIF、公钥、hash160→ 10 个地址

1. 十进制和十六进制是同一个数字

私钥是一个整数,而一个整数只有一个值。「十进制」「十六进制」不是私钥的属性,而是「怎么写它」的 选择。数值本身是各位数字的加权和,每一位的权重是进制的幂:

k = Σ di · bi   (十进制 b = 10,十六进制 b = 16)

对演示私钥来说,十进制第一位是第 76 位的 3,贡献 3 × 1075; 十六进制形式以 08 开头,贡献 0 × 1663 + 8 × 1662。 算法不同,数值完全相同。

进制使用的字符本私钥的位数一位代表适合用来
2(二进制)0 12561 比特看清曲线自身的运算;比特图案分析
10(十进制)0–976log₂(10) ≈ 3.32 比特人类数数、范围检查、「谜题」私钥
16(十六进制)0–9 a–f64正好 4 比特(一个半字节)按字节对齐显示;业界默认
58(Base58)字母数字去掉 0OIl51–52(含版本字节与校验和)log₂(58) ≈ 5.86 比特WIF 与 1…/3… 地址
32(bech32 字符集)32 个字符,刻意避开易混字符42–62(含 hrp 与校验和)正好 5 比特bc1q…/bc1p… 地址

十六进制之所以成为惯例,原因在第三列:这些进制里只有它和机器的单位对齐。4 比特是一位 hex 数字, 8 比特是两位 —— 于是 32 字节私钥正好是 64 位 hex,数一数就能看出每个字节的边界。

本页不是做什么的

它不是加密步骤,也不是「把私钥转换掉」。从十进制到十六进制的过程中没有哈希、没有 KDF、没有 校验和 —— 它只是整数上的一一映射,完全可逆。本页真正不可逆的部分都在后面: P = k·G(依赖离散对数假设的单向运算),以及地址内部的 SHA-256/RIPEMD-160 哈希。

2. 转换到底是怎么做的

教科书上有两种算法,都精确无误,区别只在于需要的草稿空间和实现手感。

反复取余(remainder method)

digits = "0123456789abcdef"
out = ""
while n > 0:
    n, r = divmod(n, 16)     # r 在 0..15
    out = digits[r] + out   # 往前面插
return out or "0"

从最低位开始产出结果,所以每得到一位都要插到最前面(或者先收集再整体反转)。 每输出一位要做一次大整数除法:32 字节私钥共 64 次。

Horner 法(从左到右)

acc = 0
for ch in decimal_string:
    acc = acc * 10 + digit(ch)
# 此时 acc 就是那个整数;
# 再用同样的技巧、以 16 为基数
# 逐位输出十六进制即可。

从最高位往下按多项式展开,每读入一位只要一次乘法和一次加法。大整数库(GMP、bcmath、 Java 的 BigInteger、Python 的 int)内部就是这么做的:读十进制 76 次 乘加,写十六进制 64 次除法。

两种算法同样正确,在定长进制下都随位数线性增长。本页之所以能在 PHP 里做这件事,是因为把活儿交给了 GMP:gmp_init("368345…", 10) 直接读十进制字符串,gmp_strval(n, 16) 直接写出 十六进制。若手工用 intval() 去做,私钥会被悄无声息地毁掉 —— 见下一节。

3. 为什么是 256 位,边界在哪里

secp256k1 的点群阶为 n,这是一个略小于 2256 的 256 位数字。 合法私钥就是 1 … n−1 这些整数。下面把它们完整写出来,因为校验器比较的就是这些确切的数:

数值十进制
最小合法私钥1
最大合法私钥:n−1115792089237316195423570985008687907852837564279074904382605163141518161494336
曲线阶 n —— 非法115792089237316195423570985008687907852837564279074904382605163141518161494337
n+1 —— 非法,若某个库放行则行为等同私钥 1115792089237316195423570985008687907852837564279074904382605163141518161494338
256 位能表示的最大数 2256−1 —— 非法115792089237316195423570985008687907853269984665640564039457584007913129639935
2256(32 字节装不下)115792089237316195423570985008687907853269984665640564039457584007913129639936

上表里 n−1 和 n 只差三位十进制数字。闭合的非法区间 [n, 2256−1] 共含 432420386565659656852420866394968145599 个整数 —— 两个端点之间的跨度是 432420386565659656852420866394968145598。用 2256 除以这个数量得到 267776665566007192515705986938822075896,也就是说整段非法区间只占 32 字节空间的大约 2.678 × 1038 分之一。这就是为什么人们通常要等到某个校验器拒绝输入,才意识到有这条边界。

2 的幂十进制值十六进制(32 字节)你会在哪里遇到它
2255578960446186580977117854925043439539266349923328202820197287920039565648199688000…0000满宽私钥的第一位;十进制形式首次出现 77 位的最小私钥
21283402823669209384634633746074317682114560000…0001 0000…0000「256 位空间的一半」这个经典标记;也是 2128 次群运算 —— 这条曲线的安全级别
264184467440737095516160000…0001 0000…0000比最大的 64 位无符号整数大一 —— 64 位算术开始溢出的位置
282560000…0100「私钥是 256」和「私钥是 256 位」是两句完全不同的话
2010000…0001最小合法私钥;它的压缩地址是 1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH

4. 大整数:为什么普通整数装不下它

每种语言的原生整数类型宽度都是固定的,而 256 位是常用最宽整数的四倍。后果不是理论上的:

类型能精确表示的最大值遇到 256 位私钥会怎样
PHP int(64 位构建) 9223372036854775807(263−1) 把演示私钥强制转成 int 会正好饱和在 9223372036854775807:私钥的低 63 位被丢掉,剩下的是一个常量。
IEEE-754 double(PHP 的 float、JavaScript 的 number) 253 = 9007199254740992 以内的整数才精确 把演示私钥转成 float,并用 sprintf('%.0f', $f) 打印,会得到 3683455675284633033626393239859223006741653855112843325067765303468422594560 —— 从第 17 位开始就是错的。(若直接用 (string) 强制转换,打印出的是 3.6834556752846E+75,反而把这个错误藏了起来。)
GMP/bcmath 任意精度 只受内存限制 精确。本页用的就是它。
静默截断是私钥被毁掉的方式

原生整数的失败模式不是报错,而是一个看起来很像样的错误数字。某个工具把你的十进制私钥读进 double、据此推导地址并显示余额,它会理直气壮地告诉你另一个私钥的余额。如果你 要自己重写这套逻辑,请从第一个字符起就把它保存为字符串或任意精度整数,绝不要让它经过 intval()、parseInt() 或 Number()。

5. 定长、补零与前导零

十进制数没有固定长度:就十进制写法而言,1、256 和演示私钥都「是一个私钥」。 但比特币把私钥序列化为恰好 32 字节,因此必须用零比特左补,直到填满整个字段:

k = 1  →  0000000000000000000000000000000000000000000000000000000000000001  (31 个前导零字节)

演示私钥恰好不需要任何补零:从右往左数第 64 位 hex 数字正好落在最高半字节的位置上,所以它的字节数 正好是 32,前导零字节数为 0 —— 尽管它最前面的四个比特是 0000。这个区别(前导零 比特 vs 前导零字节)是手工写二进制私钥时最常见的困惑来源。

十进制输入补零后的十六进制前导零字节前导零比特合法吗
00000…000032256否 —— 无穷远点
10000…000131255是
2560000…010030247是
演示私钥0824c314…04是
2256−1ffff…ffff00否 —— 超过 n

6. 整数私钥:著名的「谜题」地址长什么样

比特币生态里有一组广为人知的已充值地址 —— 所谓「puzzle(谜题)」—— 它们的私钥根本不是随机 的 256 位数字:第 i 号私钥落在区间 [2i−1, 2i) 内。换句话说, 最高的 256 − i 位被公开地知道是零。它们正是本页讨论的「小的整数私钥」,下表列出前几个以及 它们各自导出的主网 P2PKH 地址(全部由本工具实算得出):

编号私钥(十进制)私钥(hex,64 位)P2PKH 地址(压缩)
110000…00011BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH
220000…00021cMh228HTCiwS8ZsaakH8A8wze1JR5ZsP
340000…00041JtK9CQw1syfWj1WtFMWomrYdV3W2tWBF9
480000…00081EhqbyUMvvs7BfL8goY6qcPbD6YKfPqb7e
5160000…001019p7ktDbdJnmV4YLC7zQ37RsYczMZJmd6q
6320000…00201Q3pVMPLvKRNudhqz7uecd7C3iddUJLs21
7640000…004014raEyLewYMk4Xqg76xJQxEygnhWhx6mUQ
81280000…00801CAE6ej7VyAhgTtL1AYKTEByRJaCZKg8XM
105120000…02001M8az82AhB8WC9NyShQMoYK7E7wam8TeN9
1220480000…08001NDaJQKUp9TaKXgLLnM4d5ukP1WcmhDPhV
16327680000…80001GkFyhEBkkwUT9keTB8qMp2t4NQi8YcVGf
205242880000…0008 00001FFtp4xWbyoR1e4ZCZmwnx9XR6C6SPAQS

这张表给出两条教训,也正是这类私钥几乎立刻被扫空的原因:

「可我的数字不是 2 的幂」

那只会更糟,不会更好:人类想出来的数字,其熵远远低于 256 位,攻击者要猜的是规律,而不是 穷举整个空间。唯一站得住脚的私钥来源是密码学安全随机数发生器或 BIP39 助记词;本站的演示值都是刻意 做成一次性示例的,绝不守护真实资金。

7. 实例演算

下表每个值都由本页用十进制样例 3683455675284633286911943861444039993120875154046227415438637967083965608394(76 位, 位于合法区间约 3.18% 处)实时算出:

步骤值
十进制输入3683455675284633286911943861444039993120875154046227415438637967083965608394
十六进制(32 字节,无需补零)0824c314772b2c2859c889471390a36bf66e53a1ca1642f96f0f2c9307a171ca
二进制(首字节)00001000 —— 数值以 4 个零比特开始
压缩 WIFKwVYL77Lcs1ckM39NvGjrtfKhU4KKdR2iB9Wq2FSMN6rbGK5tVqG
非压缩 WIF5HssbguBnjbaUVZCsH9YuzUG7T4vYQf51iiodi4izdVy6aVNekU
压缩公钥02ff812e26116a9aa140abe629e7f8a38401653caf925119def59ed3758c67ee80
hash160(压缩)21f57b6debcfc5b67182dfb4af1641f0a8189012
P2PKH(C)146ZNjH7XTXnMd1ofe3z7CL2i8WM7N2UqT
P2PKH(U)16kR3eiswUY6tmGnxZhwQmW6LAvTLGWG2G
P2SH-P2WPKH(S)3DZT76KyKyc5zkzvLugP8umgt4RPY4XPQw
P2WPKH(W)bc1qy86hkm0telzmvuvzm76279jp7z5p3yqjnaerk6
P2TR(T)bc1pmsrhxnvmj8tjxxu9wj69ntvwvhvr28qufyc26tshz3rjj777tx3sh54u63
测试网 P2PKH(C)micWfnN6LUy38jVRPD2Mw7YMa873zjixGw
测试网 P2WPKH(W)tb1qy86hkm0telzmvuvzm76279jp7z5p3yqjemzsdf

8. 输入校验与你会看到的提示

你输入的内容会发生什么原因
3 683 455 …/3,683,455,…/3_683_455…接受,转换前去掉分隔符纯粹为了可读性 —— 是同一个整数
0Private key 0 is invalid: the range is [1, n-1]0 · G 没有坐标
115792089237316195423570985008687907852837564279074904382605163141518161494337(= n)Private key is >= the secp256k1 curve order n…是合法的 32 字节数值,但不是合法私钥
超过 2256−1 的 78 位数字Value is 260 bits, which exceeds the expected 256 bits它根本无法序列化成 32 字节
1.5 或 -5Not a valid decimal integer: 1.5只接受数字(及分隔符);不存在小数私钥或负数私钥
留空页面停留在「还没有输入」状态空输入绝不会回退到演示值

9. 推导链上的下一步

10. 安全须知

11. 常见错误

12. 速查表

项目取值 / 规则
输入十进制整数,只含数字;空格、逗号、下划线会被忽略
合法范围1 … 115792089237316195423570985008687907852837564279074904382605163141518161494336
范围内的十进制位数1 到 78 位(演示私钥是 76 位)
输出宽度始终 64 位 hex/32 字节,左补零
可逆吗可逆 —— 十进制 ⇄ 十六进制无损;公钥那一步不可逆
PHP 原生整数上限9223372036854775807(263−1)—— 请改用 GMP
JSON/JS 安全整数上限253 = 9007199254740992