十进制私钥 → HEX、WIF 与地址
按人类书写数字的方式输入私钥 —— 一个大整数 —— 本页把它转换成规范的 256 位 HEX 形式,再推导出两种 WIF、两种公钥、两个 hash160 以及全部十个地址。空格、逗号与下划线会被忽略。
请在上方输入内容后点击「转换」。不知道填什么?点「填入示例」即可载入占位符里的演示数据。
本页计算了什么
本页接受按人类习惯写出来的私钥 —— 一个普通的十进制整数 —— 把它转换成规范的 256 位十六进制形式,
然后沿着整条推导链算下去。转换前会先去掉空格、逗号和下划线,因为
3 683 455 675 …、3,683,455,675… 和 3683455675… 是同一个数字 ——
分隔符是给人看的,不是给计算机看的。
1. 十进制和十六进制是同一个数字
私钥是一个整数,而一个整数只有一个值。「十进制」「十六进制」不是私钥的属性,而是「怎么写它」的 选择。数值本身是各位数字的加权和,每一位的权重是进制的幂:
对演示私钥来说,十进制第一位是第 76 位的 3,贡献 3 × 1075;
十六进制形式以 08 开头,贡献 0 × 1663 + 8 × 1662。
算法不同,数值完全相同。
| 进制 | 使用的字符 | 本私钥的位数 | 一位代表 | 适合用来 |
|---|---|---|---|---|
| 2(二进制) | 0 1 | 256 | 1 比特 | 看清曲线自身的运算;比特图案分析 |
| 10(十进制) | 0–9 | 76 | log₂(10) ≈ 3.32 比特 | 人类数数、范围检查、「谜题」私钥 |
| 16(十六进制) | 0–9 a–f | 64 | 正好 4 比特(一个半字节) | 按字节对齐显示;业界默认 |
| 58(Base58) | 字母数字去掉 0OIl | 51–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−1 | 115792089237316195423570985008687907852837564279074904382605163141518161494336 |
| 曲线阶 n —— 非法 | 115792089237316195423570985008687907852837564279074904382605163141518161494337 |
| n+1 —— 非法,若某个库放行则行为等同私钥 1 | 115792089237316195423570985008687907852837564279074904382605163141518161494338 |
| 256 位能表示的最大数 2256−1 —— 非法 | 115792089237316195423570985008687907853269984665640564039457584007913129639935 |
| 2256(32 字节装不下) | 115792089237316195423570985008687907853269984665640564039457584007913129639936 |
上表里 n−1 和 n 只差三位十进制数字。闭合的非法区间
[n, 2256−1] 共含
432420386565659656852420866394968145599 个整数 —— 两个端点之间的跨度是
432420386565659656852420866394968145598。用 2256 除以这个数量得到
267776665566007192515705986938822075896,也就是说整段非法区间只占 32 字节空间的大约
2.678 × 1038 分之一。这就是为什么人们通常要等到某个校验器拒绝输入,才意识到有这条边界。
| 2 的幂 | 十进制值 | 十六进制(32 字节) | 你会在哪里遇到它 |
|---|---|---|---|
| 2255 | 57896044618658097711785492504343953926634992332820282019728792003956564819968 | 8000…0000 | 满宽私钥的第一位;十进制形式首次出现 77 位的最小私钥 |
| 2128 | 340282366920938463463374607431768211456 | 0000…0001 0000…0000 | 「256 位空间的一半」这个经典标记;也是 2128 次群运算 —— 这条曲线的安全级别 |
| 264 | 18446744073709551616 | 0000…0001 0000…0000 | 比最大的 64 位无符号整数大一 —— 64 位算术开始溢出的位置 |
| 28 | 256 | 0000…0100 | 「私钥是 256」和「私钥是 256 位」是两句完全不同的话 |
| 20 | 1 | 0000…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 字节,因此必须用零比特左补,直到填满整个字段:
演示私钥恰好不需要任何补零:从右往左数第 64 位 hex 数字正好落在最高半字节的位置上,所以它的字节数
正好是 32,前导零字节数为 0 —— 尽管它最前面的四个比特是 0000。这个区别(前导零
比特 vs 前导零字节)是手工写二进制私钥时最常见的困惑来源。
| 十进制输入 | 补零后的十六进制 | 前导零字节 | 前导零比特 | 合法吗 |
|---|---|---|---|---|
0 | 0000…0000 | 32 | 256 | 否 —— 无穷远点 |
1 | 0000…0001 | 31 | 255 | 是 |
256 | 0000…0100 | 30 | 247 | 是 |
| 演示私钥 | 0824c314… | 0 | 4 | 是 |
| 2256−1 | ffff…ffff | 0 | 0 | 否 —— 超过 n |
6. 整数私钥:著名的「谜题」地址长什么样
比特币生态里有一组广为人知的已充值地址 —— 所谓「puzzle(谜题)」—— 它们的私钥根本不是随机
的 256 位数字:第 i 号私钥落在区间 [2i−1, 2i) 内。换句话说,
最高的 256 − i 位被公开地知道是零。它们正是本页讨论的「小的整数私钥」,下表列出前几个以及
它们各自导出的主网 P2PKH 地址(全部由本工具实算得出):
| 编号 | 私钥(十进制) | 私钥(hex,64 位) | P2PKH 地址(压缩) |
|---|---|---|---|
| 1 | 1 | 0000…0001 | 1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH |
| 2 | 2 | 0000…0002 | 1cMh228HTCiwS8ZsaakH8A8wze1JR5ZsP |
| 3 | 4 | 0000…0004 | 1JtK9CQw1syfWj1WtFMWomrYdV3W2tWBF9 |
| 4 | 8 | 0000…0008 | 1EhqbyUMvvs7BfL8goY6qcPbD6YKfPqb7e |
| 5 | 16 | 0000…0010 | 19p7ktDbdJnmV4YLC7zQ37RsYczMZJmd6q |
| 6 | 32 | 0000…0020 | 1Q3pVMPLvKRNudhqz7uecd7C3iddUJLs21 |
| 7 | 64 | 0000…0040 | 14raEyLewYMk4Xqg76xJQxEygnhWhx6mUQ |
| 8 | 128 | 0000…0080 | 1CAE6ej7VyAhgTtL1AYKTEByRJaCZKg8XM |
| 10 | 512 | 0000…0200 | 1M8az82AhB8WC9NyShQMoYK7E7wam8TeN9 |
| 12 | 2048 | 0000…0800 | 1NDaJQKUp9TaKXgLLnM4d5ukP1WcmhDPhV |
| 16 | 32768 | 0000…8000 | 1GkFyhEBkkwUT9keTB8qMp2t4NQi8YcVGf |
| 20 | 524288 | 0000…0008 0000 | 1FFtp4xWbyoR1e4ZCZmwnx9XR6C6SPAQS |
这张表给出两条教训,也正是这类私钥几乎立刻被扫空的原因:
- 已知区间把 2256 的搜索变成小得多的搜索。如果你知道私钥落在
[2i−1, 2i)内,候选数量就从2256降到2i−1。针对已知区间,Pollard kangaroo 算法的代价约为2i/2次点加:i = 40时约一百万次,i = 64时约 232 次(一台笔记本跑一周),i = 128时是 264 次,已经不可 企及。本表靠前的那些私钥并不是「难以猜到」,它们只是算术练习题。 - 可被认出的地址让情况更糟。这些私钥早就公开了,它们的地址也在公开名单上。扫币的人
根本不用搜索:他们盯着这些地址,只要有人转入,就在同一个区块里花掉。像
115792089237316195423570985008687907852837564279074904382605163141518161494337(也就是n本身)或者2255(导出18h7RmwXCTYX69z9S2Hc9gs8ET7SUN7YG5)这种「自作聪明」的私钥,属于完全同一类。
那只会更糟,不会更好:人类想出来的数字,其熵远远低于 256 位,攻击者要猜的是规律,而不是 穷举整个空间。唯一站得住脚的私钥来源是密码学安全随机数发生器或 BIP39 助记词;本站的演示值都是刻意 做成一次性示例的,绝不守护真实资金。
7. 实例演算
下表每个值都由本页用十进制样例
3683455675284633286911943861444039993120875154046227415438637967083965608394(76 位,
位于合法区间约 3.18% 处)实时算出:
| 步骤 | 值 |
|---|---|
| 十进制输入 | 3683455675284633286911943861444039993120875154046227415438637967083965608394 |
| 十六进制(32 字节,无需补零) | 0824c314772b2c2859c889471390a36bf66e53a1ca1642f96f0f2c9307a171ca |
| 二进制(首字节) | 00001000 —— 数值以 4 个零比特开始 |
| 压缩 WIF | KwVYL77Lcs1ckM39NvGjrtfKhU4KKdR2iB9Wq2FSMN6rbGK5tVqG |
| 非压缩 WIF | 5HssbguBnjbaUVZCsH9YuzUG7T4vYQf51iiodi4izdVy6aVNekU |
| 压缩公钥 | 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… | 接受,转换前去掉分隔符 | 纯粹为了可读性 —— 是同一个整数 |
0 | Private 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 或 -5 | Not a valid decimal integer: 1.5 | 只接受数字(及分隔符);不存在小数私钥或负数私钥 |
| 留空 | 页面停留在「还没有输入」状态 | 空输入绝不会回退到演示值 |
9. 推导链上的下一步
- 十六进制私钥 → 全部结果 —— 总计算器:全部表示形式、两种 WIF、十个地址一屏看完。
- 二进制私钥 —— 同一个私钥写成 256 个比特并标出位号。
- Base64 私钥 —— 针对既不是 hex 也不是十进制的钱包导出格式。
- 私钥 → 压缩公钥 —— 转换之后的下一步。
10. 安全须知
- 十进制私钥依然是私钥。用十进制写秘密什么都藏不住;以十进制整数公开的私钥,和 WIF 一样彻底暴露。
- 位数一位都不能错。一个少了某位的 76 位私钥就是另一个私钥,通常还是合法的,于是它会 显示余额为零,而你的真币安然未动 —— 更糟的情况是它恰好是攻击者用「近似笔误」搜索出来的私钥。
- 绝不四舍五入或重新排版。千位分隔符只是装饰,但「3.68 × 1075」就是信息 丢失。私钥要以字符串保存,用文件保存精确字节;备份请用 WIF 或 BIP39 助记词,而不是你手打过的 数字。
- 记住这件事的本质。本页一切都是公开数学:拿到十进制私钥的人可以花掉币,而只拿到地址 的人找不到私钥。这种不对称就是整个安全模型。
11. 常见错误
- 把十进制形式当成「更保密」。它是同一个值;隐蔽不等于加密。
- 用
intval()/Number()/parseInt()。它们会在 63 位或 53 位处截断,返回一个看起来正常的错误数字。 - 把 256(一个数)和 256 位(一个宽度)搞混。私钥
256是0000…0100,一把极其普通的低熵私钥。 - 以为最大值是固定的。
2256−1不是私钥,n−1才是。 上界由曲线阶决定,而不是由字段宽度决定。 - 补零补错了边。补零永远在左边。在右边补零等于把数值乘以 16。
- 把 WIF 或 hex 字符串粘到这里。
K…字符串或0824c314…不是 十进制整数,会被拒绝 —— 请使用对应的页面。
12. 速查表
| 项目 | 取值 / 规则 |
|---|---|
| 输入 | 十进制整数,只含数字;空格、逗号、下划线会被忽略 |
| 合法范围 | 1 … 115792089237316195423570985008687907852837564279074904382605163141518161494336 |
| 范围内的十进制位数 | 1 到 78 位(演示私钥是 76 位) |
| 输出宽度 | 始终 64 位 hex/32 字节,左补零 |
| 可逆吗 | 可逆 —— 十进制 ⇄ 十六进制无损;公钥那一步不可逆 |
| PHP 原生整数上限 | 9223372036854775807(263−1)—— 请改用 GMP |
| JSON/JS 安全整数上限 | 253 = 9007199254740992 |