hash160 → P2PKH / P2SH / P2WPKH 地址
hash160 是 20 字节的指纹 RIPEMD160(SHA256(公钥))。它本身不能变成地址:加上版本字节与校验和是 1…、3… 地址,做成 bech32 则是 bc1q…。本页把所有包装方式并排展示出来 —— 并说明为什么 Taproot 地址永远不可能仅凭它生成。
请在上方输入内容后点击「转换」。不知道填什么?点「填入示例」即可载入占位符里的演示数据。
本页计算了什么
你输入一个值 —— 20 字节的 hash160 —— 页面会列出所有能由它构建出来的地址,并显示每个地址 背后真正被承诺的那串字节。这个哈希本身就是一行运算:
本页从第三个方框开始:哈希已经算完,下面全部都是纯包装。而这恰恰是最值得弄懂的部分 ——
同一串 20 字节,前面粘上不同的字节,就会变成 1…、3…、bc1q… 或
tb1q… 地址。
1. 什么是密码学哈希函数
哈希函数把任意长度的输入变成固定长度的指纹。密码学界对它有三项彼此独立的要求,而在比特币地址里, 这三项各自承担着不同的职责。
| 性质 | 含义 | 160 位输出所需的代价 | 在这里保护什么 |
|---|---|---|---|
| 原像抗性 | 给定摘要 h,找出任意一个满足 H(x) = h 的输入 x | 约 2160 = 1461501637330902918203684832716283019655932542976 次尝试 | 阻止任何人凭空造出一个新的公钥、让它的哈希等于你的地址,然后用自己那对密钥把钱花掉 |
| 第二原像抗性 | 给定某个确定的输入 x,找出另一个 x′ 使 H(x′) = H(x) | 约 2160 | 当你的公钥已经公开后起作用:没人能把另一个公钥替换成你刚刚花过的那一个 |
| 抗碰撞性 | 找出任意两个输入 x ≠ x′,使两者摘要相同 | 约 280 = 1208925819614629174706176(生日界) | 阻止对手造出两个共享同一地址的密钥:给你看无害的那个,用另一个去花钱 |
第一项最容易被人误读。地址本身就是那个哈希,所以根本不存在「从地址反推出公钥就完了」 这种说法 —— 详见第 4 节。原像抗性真正给你的是:映射到某个地址的公钥集合实际上无法被触及。要花掉一笔 P2PKH 输出,你必须公开一个 hash160 恰好等于该地址的公钥,并且用它对应的私钥签名;而攻击者 可以同时自选这两样东西。假如原像只需要 240 步而不是 2160 步,攻击者 就会直接新造一对密钥、让公钥的哈希等于你的地址,然后把它清空。正是原像抗性,让一个公开出来的地址可以 永远安全地躺在那里不被花掉。
2. 为什么是 RIPEMD160(SHA256(x)),而不是单一哈希
前后两段都是刻意设计的,它们回答的是两个不同的问题。
| 构造方式 | 输出 | 抗碰撞性 | 原像抗性 | 取舍 |
|---|---|---|---|---|
SHA256(x) | 32 字节 | 2128 | 2256 | 碰撞强度最高,但脚本里、UTXO 集里每个输出都要多出 12 字节 |
RIPEMD160(x) | 20 字节 | 280 | 2160 | 紧凑,但攻击者和你之间只隔着一个哈希函数 |
SHA256(x) 截断到 20 字节 | 20 字节 | 280 | 2160 | 没有第二个函数;而且沿用同一套内部状态与填充规则 |
RIPEMD160(SHA256(x)) | 20 字节 | 280 | 2160 | 两种独立设计串联 —— 比特币采用的就是它 |
把它想成一条流水线。SHA-256 是现代、被充分研究的 256 位函数;先跑它,会让进入第二级的值变成均匀随机的 32 字节串,于是 RIPEMD-160 永远不会看到攻击者精心构造的输入。接着 RIPEMD-160 把承诺值压缩到 20 字节,而这个节省是实打实的:
| 项目 | 20 字节承诺值 | 32 字节承诺值 | 每个输出节省 |
|---|---|---|---|
P2PKH 的 scriptPubKey | 25 字节(76a914 ‖ 20 字节 ‖ 88ac) | 37 字节 | 12 字节 |
| Base58Check 地址 | 34 个字符(编码 25 字节) | 约 50 个字符 | 16 个字符 |
| Witness v0 程序 | 20 字节(P2WPKH) | 32 字节(P2WSH 级别) | 12 字节 |
12 字节乘以链上每一个未花费输出、而且是永久的,这个理由已经足够强。第二个理由是纵深防御:某一个函数
被攻破并不会立刻让整个构造失效。要在 RIPEMD160(SHA256(x)) 上伪造碰撞,攻击者必须造出两个
SHA-256 摘要相同的输入 —— 也就是说他得连 SHA-256 一起攻破,或者在一个只能控制 32 字节输入的
接口上攻击 RIPEMD-160。
把两个哈希串起来不会让安全性相乘。RIPEMD160(SHA256(x)) 的抗碰撞性依然
受这条攻击路径上最弱的一环限制 —— RIPEMD-160 的 280 生日界 —— 因为只要最终输出碰撞
就够了。这种串联换来的是对密码分析型攻破的抵抗,以及让内层函数只接受固定 32 字节输入,而不是
一个更大的数字。
3. 生日界,以及为什么 160 位够用
原像攻击的代价与输出空间成正比,也就是 2160。碰撞之所以便宜,是因为生日悖论:一个房间里有 23 个人就很可能有人同一天生日;对哈希而言,期望搜索量约为
| 摘要长度 | 原像代价 | 碰撞代价 | 使用者 |
|---|---|---|---|
| 128 位 | 2128 | 264 | MD5 一类的设计 —— 现实中早已被攻破 |
| 160 位 | 2160 | 280 | hash160:比特币地址里的 RIPEMD-160 |
| 256 位 | 2256 | 2128 | SHA-256:外层哈希,以及 Taproot 的 tagged hash |
280 是 hash160 诚实的薄弱点,而它被认为可以接受,原因有三:碰撞只有在攻击者还能说服别人 使用那两把碰撞密钥之一时才有收益;攻击者还必须同时匹配 SHA-256,因为第二级只接受 32 字节输入;而且 RIPEMD-160 的 160 位宽度是经过国际标准评审的选择(由欧盟 RIPE 项目选出),不是某人的第一次尝试。 如果你在为别人生成地址,而对方从不核实你是否知道私钥,那么保护他的就是抗碰撞性 —— 恰恰是余量最小的那 一项。
4. 地址不是秘密 —— 真正保护币的是什么
看看一个真实地址的里面:146ZNjH7…2UqT 无非就是 Base58Check(0x00 ‖ hash160)。
哈希就在地址里,它出现在每一张发票、每一个二维码、每一个区块浏览器上。没有人打算藏它,
「你无法从哈希反推出我的地址」根本不是安全论证 —— 地址本来就是主动公开的。
保护币的是三件事的组合:
- 私钥。 花费需要对该笔交易的有效 ECDSA 签名。地址里没有任何东西能让你造出签名。
- hash160 的原像抗性。 想找出另一个哈希等于你地址的公钥,代价约 2160, 必须不可行 —— 因为那样一把公钥可以用攻击者自己生成的签名花掉。
- 在你花费之前,公钥不在链上。 P2PKH 输出未花费时,链上只存那 20 字节哈希。完整的
点要等到花费它的那笔交易的
scriptSig里才出现。
| 地址类型 | 未花费时链上存什么 | 花费时暴露什么 | 量子暴露 |
|---|---|---|---|
P2PKH(1…) | 公钥的 hash160 | 33 或 65 字节公钥 | 低(花费前):只暴露一个 160 位原像问题 |
P2SH-P2WPKH(3…) | hash160(0x0014 ‖ hash160) | 22 字节 redeemScript 与公钥 | 低(花费前) |
P2WPKH(bc1q…) | 20 字节 witness 程序 | 压缩公钥 | 低(花费前) |
P2TR(bc1p…) | 32 字节 x-only 输出公钥 —— 一个曲线点 | 一个签名(key path) | 从入账那一刻起就高 |
最后一行正是「抗量子」讨论里为什么哈希依然重要的原因。Shor 算法能解椭圆曲线离散对数,因此可以从链上 可见的公钥恢复私钥。而一笔未花费的 P2PKH 输出上没有任何点可见 —— 只有哈希 —— 于是量子攻击者只能去攻 哈希,而 Grover 算法只带来平方级加速(2160 降到大约 280 次量子操作)。Taproot 选的 是相反的取舍:它的输出公钥本身就是链上的一个曲线点,这让验证更省、协作更私密,同时也让它成为量子对手 最先能拿走的东西。
5. 本页打印内容的字节级布局
| 地址 | 送进编码器的字节 | 长度 | 开头字符 |
|---|---|---|---|
| P2PKH 主网 | 0x00 ‖ hash160 | 21 字节 + 4 字节校验和 | 1…,恒为 34 个字符 |
| P2PKH 测试网 | 0x6F ‖ hash160 | 21 字节 + 4 字节 | m… 或 n… |
| P2SH-P2WPKH 主网 | 0x05 ‖ hash160(0x0014 ‖ hash160) | 21 字节 + 4 字节 | 3… |
| P2SH-P2WPKH 测试网 | 0xC4 ‖ hash160(0x0014 ‖ hash160) | 21 字节 + 4 字节 | 2… |
| P2WPKH 主网 | "bc" + 分隔符 + witness v0 + 32 个 5 位字 | 42 个字符 | bc1q… |
| P2WPKH 测试网 | "tb" + 分隔符 + witness v0 + 同样的字 | 42 个字符 | tb1q… |
请注意 P2SH-P2WPKH 那一行的双重哈希。嵌套 SegWit 地址并不直接承诺你的公钥哈希;它承诺的是 22 字节
redeemScript 0x0014 ‖ hash160 的 hash160。这就是为什么它的载荷那 20 字节和其余
各行都不一样。
6. 用示例 hash160 做的完整演算
下面这些就是本页对 21f57b6d…89012 实际打印的值,全部现场算出,没有从任何地方抄来:
| 步骤 | 值 |
|---|---|
| 公钥的 SHA-256 | 067eb00a0b9864633b020eef374476142daba913c5481ad6a4741cc8ab702617 |
| 再取 RIPEMD-160 = hash160 | 21f57b6debcfc5b67182dfb4af1641f0a8189012 |
P2PKH 载荷 00 ‖ hash160 | 0021f57b6debcfc5b67182dfb4af1641f0a8189012 |
| 它的双 SHA256 校验和(前 4 字节) | cbd7667e |
| P2PKH 主网地址 | 146ZNjH7XTXnMd1ofe3z7CL2i8WM7N2UqT |
P2PKH 测试网载荷 6F ‖ hash160 | 6f21f57b6debcfc5b67182dfb4af1641f0a8189012(校验和 8c66f080) |
| P2PKH 测试网地址 | micWfnN6LUy38jVRPD2Mw7YMa873zjixGw |
RedeemScript 0014 ‖ hash160 | 001421f57b6debcfc5b67182dfb4af1641f0a8189012 |
| 它的 hash160 = 脚本哈希 | 823333d5fd23a83661e8e47629552c4a5bfc8b6e |
P2SH 载荷 05 ‖ 脚本哈希 | 05823333d5fd23a83661e8e47629552c4a5bfc8b6e(校验和 acbfef44) |
| P2SH-P2WPKH 主网地址 | 3DZT76KyKyc5zkzvLugP8umgt4RPY4XPQw |
| P2SH-P2WPKH 测试网地址 | 2N57fAqFzwS7SCYdU23JFkrkx6QdZKurmpU |
| P2WPKH 主网地址 | bc1qy86hkm0telzmvuvzm76279jp7z5p3yqjnaerk6 |
| P2WPKH 测试网地址 | tb1qy86hkm0telzmvuvzm76279jp7z5p3yqjemzsdf |
| witness 程序字(版本 0 之后) | y86hkm0telzmvuvzm76279jp7z5p3yqj + 校验和 naerk6 |
P2PKH 的 scriptPubKey | 76a91421f57b6debcfc5b67182dfb4af1641f0a818901288ac |
P2WPKH 的 scriptPubKey | 001421f57b6debcfc5b67182dfb4af1641f0a8189012 |
六个不同的地址,一个哈希,除了那两次哈希调用之外没有任何密码学。只要在上游改动任意一个输入字节, 上面每一行都会跟着变。
7. Taproot 地址无法仅凭 hash160 生成
这是本页唯一一件做不到的事,而且原因是结构性的,不是本工具的限制。P2TR 输出承诺的是一个 32 字节的 x-only 输出公钥,算法是
要算出它就需要完整的曲线点:tweak 是 taggedHash("TapTweak", x(P)),点加需要真实存在的、有
确定 y 的点,而且结果必须是持有者真的能用私钥操作的点。hash160 是 20 字节摘要;它不是点,没有 y,更关键的
是 —— 即使曲线方程对它恰好有解,也没有人知道把它当作 x 坐标得到那个点的离散对数。
| P2TR 需要什么 | hash160 能提供什么 |
|---|---|
| 真实密钥的 32 字节 x 坐标 | 20 字节;比合法域元素短 12 字节 |
| 持有者掌握其私钥的点 | 一个摘要 —— 没有已知对应的标量 |
| 由内部公钥导出的 TapTweak | 没有东西可以 tweak,tweak 无从计算 |
| bech32m、witness 版本 1、32 字节程序 | 只有 bech32 v0(20 字节)或 Base58Check 载荷 |
就本示例而言,把这 20 字节左补零到 32 字节当作 x 坐标,居然真能落到曲线上的一个合法点,得到
bc1pkc3xmm086pdgtvrkcg33cn90lhv9aq6f3ueuu9gvwdeeqrzmr5qsejuhs7。但那把私钥没有任何人
拥有。往那里打币,和打进销毁地址没有区别。同一个密钥真正的 Taproot 地址是
bc1pmsrhxnvmj8tjxxu9wj69ntvwvhvr28qufyc26tshz3rjj777tx3sh54u63,它只能从完整公钥
02ff812e…ee80 推导,绝不可能从它的哈希推出来。
8. 这个值从哪来、接下来去哪
- 上游: 压缩公钥 → hash160 → 地址 演示哈希这一步本身; 十六进制私钥 → 全部格式 则从最开头开始。
- 下游之 Base58Check: Base58Check 编码 / 解码 会接收上面 打印的载荷,拆出其中的版本字节、校验和与内部结构。
- 下游之 bech32: Bech32 / Bech32m 解码 对
bc1q…形式做同样的事情,包括 witness 程序与校验和。 - 同一私钥的其它地址: P2PKH、 P2SH-P2WPKH、P2WPKH。
9. 安全须知与常见错误
- 地址不是秘密。 hash160 天生就是公开的;请把每一个公开过的地址都视为永远人尽皆知。
- 哈希了错误的序列化形式。 压缩公钥(
02…/03…)与非压缩公钥 (04…)哈希结果不同,所以同一个私钥会有两个 P2PKH 地址。演示值分别是21f57b6d…9012(压缩 →146ZNjH7…)和3f0e966d…23f9(非压缩 →16kR3eis…)。 - 以为校验和能证明含义。 Base58Check 校验和只能证明字符串没被打错;它完全不说明版本 字节是否与你所在的网络匹配。
- 以为 20 字节「太弱」。 160 位原像抗性远超任何经典攻击;最弱的一环是 80 位碰撞界, 而要利用它,代价远不止暴力枚举。
- 发到了错误的地址类型。 上面四种 Base58 / bech32 形式对应四个不同的
scriptPubKey。发到其中一个的币,只认识另一个的钱包是花不掉的。
本页所有数值都由提供页面的这个 PHP 进程计算。不会向任何地方发送数据,你粘贴的 hash160 也不会被 记录。
10. 速查表
| 项目 | 值 |
|---|---|
| 公式 | RIPEMD160(SHA256(公钥)) |
| 输出长度 | 20 字节 / 40 位十六进制 / 160 位 |
| 可由它导出的地址 | P2PKH(主网 + 测试网)、P2SH-P2WPKH(主网 + 测试网)、P2WPKH(主网 + 测试网) |
| 不能导出的地址 | P2TR / Taproot —— 需要完整曲线点 |
| Base58Check 载荷长度 | 21 字节(1 版本字节 + 20 内容字节),外加 4 字节校验和 |
| P2PKH 地址长度 | 两个网络都是 34 个字符 |
| P2WPKH 地址长度 | 42 个字符(bc1q… 或 tb1q…) |
| P2SH-P2WPKH 载荷 | 是 hash160(0x0014 ‖ hash160),不是 hash160 本身 |
| 原像抗性 | 2160 |
| 抗碰撞性 | 280(生日界) |