私钥 → P2WPKH 地址(bech32)
原生 SegWit 的 bc1q… 地址,逐层构建:压缩公钥 → hash160(20 字节 witness 程序)→ bech32 的 5 位数据字 → 6 字符校验和 → 地址。每一层都单独展示,方便你手工核对整条链路。
请在上方输入内容后点击「转换」。不知道填什么?点「填入示例」即可载入占位符里的演示数据。
本页计算了什么
你给它一个 256 位的私钥,它返回这个私钥对应的原生 SegWit 地址 —— 也就是以
bc1q 开头的字符串。本页不只是把最终答案丢给你,而是把推导的每一层都单独列出来,方便你逐层
互相验证:
1. SegWit 到底改了什么,为什么会有这种地址
「SegWit」(隔离见证,BIP141/143/173)于 2017 年 8 月 24 日激活。人们常把它当成一次改动,其实是四件事, 而这种地址类型正是它们共同的外在表现。
交易可塑性(malleability)。 在 SegWit 之前,ECDSA 签名是装在它所授权的那笔输入的
scriptSig 里的。签名是 DER 编码的两个整数,而同一个数学意义上的签名可以有好几种不同的字节
写法 —— 所以第三方可以重新编码这个签名、或者在外面再包一层多余的 push 操作,而交易依然有效。这会改变
交易 ID:钱照旧转走,但任何已经承诺了旧 txid 的二层协议(未确认的子交易、支付通道、闪电网络的前身)就
崩了。修复办法是结构性的:先把输入签好,再把签名移出交易本体,放进一个并行的
witness(见证)结构。txid 现在只由不含 witness 数据的序列化结果计算,
因此再也不能通过改动签名来改变;另有一个 wtxid 覆盖 witness 部分。
用「区块权重」取代「区块大小」。 区块不再以字节计量,而是以 权重单位(WU)计量。非 witness 字节每个计 4 WU,witness 字节每个计 1 WU。上限是 4,000,000 WU,这既保留了原先对区块中非 witness 部分 1 MB 的限制,又在其上留出了容纳 witness 数据的 空间。
见证折扣(witness discount)。 因为 witness 字节在权重上便宜 4 倍,把数据搬进 witness 就直接降低了手续费。花费一个 P2WPKH 输出的权重,大约只有花费同等 P2PKH 输出的三分之一 —— 下表的数字是 按一入账输入的精确字节数算出来的,不是道听途说的经验值。
脚本版本化。 「witness 程序」是一个字节串加一个版本号,共识规则由版本号决定。版本 0 是 P2WPKH/P2WSH,版本 1 是 Taproot。这条升级通道,正是 SegWit 对未来和对当下同样重要的原因。
2. 手续费的节省从哪来
一个 P2WPKH 输入带着空的 scriptSig(只有一个字节,即长度 00),签名与公钥都
放进 witness。下表假设只有一个输入、DER 签名长 72 字节、压缩公钥 33 字节、Taproot 的 Schnorr 签名
64 字节;vsize 为权重 ÷ 4(按节点做法向上取整)。
| 输入类型 | 非 witness 字节 | witness 字节 | 权重(WU) | vsize |
|---|---|---|---|---|
| P2PKH(压缩公钥) | 148 | 无 | 592 | 148 vB |
| P2SH-P2WPKH(嵌套) | 64 | 108 | 364 | 91 vB |
| P2WPKH(本页) | 41 | 108 | 272 | 68 vB |
| P2TR key path | 41 | 66 | 230 | 57.5 vB |
同一个单密钥花费,P2WPKH 比 P2PKH 轻 54.1%(还没有算输出部分的差异)。在网络繁忙时,正是这个差距
促使所有钱包把用户迁移到 bc1q 地址上。
3. witness 程序的字节结构:OP_0 <20 字节推送>
真正写在链上的是一个 22 字节的输出脚本。地址只是它中间那 20 个字节的、给人看的编码形式。
| 偏移 | 字节数 | 内容 | 含义 |
|---|---|---|---|
| 0 | 1 | 00 | OP_0 —— 推送一个空数组,同时也表示 witness 版本 0 |
| 1 | 1 | 14 | 推送接下来的 20 字节(0x14 = 20) |
| 2 | 20 | hash160 | witness 程序:RIPEMD160(SHA256(压缩公钥)) |
花费它时,witness 栈里恰好提供两项:一个签名和完整的压缩公钥。脚本解释器对公钥做哈希、与程序里的 20 字节比对、再验证签名确实由该公钥产生。程序本身既不承诺签名的编码方式,脚本里也没有任何东西 需要被执行 —— 可塑性问题的入口就是这样被彻底堵住的。
BIP143 要求版本 0 的 witness 花费必须使用压缩公钥。如果用 65 字节非压缩公钥算出的 20 字节程序,
会得到一个看起来完全正常、却没有任何标准钱包能花掉的 bc1q… 字符串。如果你发现同一个
私钥出现了两个不同的 bc1q 地址,八成就是这个错误:一个来自压缩公钥,另一个来自非压缩公钥。
4. 逐字节拆解 bech32
bech32(BIP173)是一种带校验和的 base32 编码,其设计目标是方便二维码扫描和口头念读。一个地址恰好由 四部分组成:
| 部分 | 示例(演示地址) | 规则 |
|---|---|---|
人类可读部分(hrp) | bc | bc = 主网,tb = 测试网;1–83 个字符,小写 |
| 分隔符 | 1 | 字符串中最后一个 1;1 不在数据字符集里,所以永远不会歧义 |
| 数据部分 | q + 32 个字符 | witness 版本,然后是程序转换成的 5 位字 |
| 校验和 | naerk6 | 最后 6 个字符;GF(32) 上的 BCH 码,把 hrp 也算进去 |
数据载荷里那 32 个字符,不是把 20 个程序字节直接写出来。base32 的字母表有 32 个符号,一个字符 代表 5 位;而程序是一串 8 位的字节。于是 bech32 要重新分组比特流:取程序的 160 位,输出 160 ÷ 5 = 32 组 5 位。这里不需要补位,因为 160 能被 5 整除;换成 32 字节的程序(Taproot)除不尽,最后一 个字的右侧会用 0 补齐。
每个 5 位组去索引下面这张字母表(比特币在所有 bech32 场景中用的都是它):
| 值 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 字符 | q | p | z | r | y | 9 | x | 8 | g | f | 2 | t | v | d | w | 0 |
| 值 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
| 字符 | s | 3 | j | n | 5 | 4 | k | h | c | e | 6 | m | u | a | 7 | l |
请留意缺席的字符:1、b、i、o。它们被排除,
是因为手抄或看屏幕时人最容易混淆它们(1/l、0/o、
b/6)。这张字母表是为人类誊写而设计的,不是为了紧凑。
校验和是一个 BCH 码:用一个 30 位的多项式累加器(polymod)吃进
hrpExpand(hrp) ‖ 数据 ‖ 000000,再与常量 1 异或(bech32),最后拆成 6 个 5 位
字符。它公开标称的检错能力,正是人们敢把它用在钱上的原因:任何影响不超过 4 个字符的错误都能被
检出,而对于更大的错误,漏检概率低于 109 分之一。由于 hrp 也参与计算,把
bc 改成 tb 同样会让校验和失效 —— 本页会真的去改动演示地址再重新解码,把这两条
都验证一遍。
大小写规则。 bech32 字符串必须整体小写或整体大写。大小写混用是硬性失败,而不是「顺手 规整一下」的机会 —— 否则同一段程序就会有两种不同的合法字符串。链上与钱包里的规范形式是小写;大写形式 的存在,是为了让二维码或被打印出来的标签在誊写时不产生歧义。
5. 实例演算 —— 真实的演示私钥
下面全部是本页对示例私钥实际算出的值;结果面板里的每一项也会根据你的输入实时重算。
| 层次 | 取值 |
|---|---|
私钥 k | 0824c314772b2c2859c889471390a36bf66e53a1ca1642f96f0f2c9307a171ca |
| 压缩公钥(33 字节) | 02ff812e26116a9aa140abe629e7f8a38401653caf925119def59ed3758c67ee80 |
| 对该公钥做 SHA-256 | 067eb00a0b9864633b020eef374476142daba913c5481ad6a4741cc8ab702617 |
| hash160 = witness 程序 | 21f57b6debcfc5b67182dfb4af1641f0a8189012 |
| 输出脚本 | 001421f57b6debcfc5b67182dfb4af1641f0a8189012(22 字节) |
数据部分(q = 版本 0,后接 32 个字) | qy86hkm0telzmvuvzm76279jp7z5p3yqj |
| 程序对应的 5 位值 | 4 7 26 23 22 27 15 11 25 31 2 27 12 28 12 2 27 30 26 10 30 5 18 1 30 2 20 1 17 4 0 18 |
| 校验和字符 | naerk6(对应值 19 29 25 3 22 26) |
| P2WPKH 地址(42 个字符) | bc1qy86hkm0telzmvuvzm76279jp7z5p3yqjnaerk6 |
| 同一私钥的测试网地址 | tb1qy86hkm0telzmvuvzm76279jp7z5p3yqjemzsdf |
注意那个测试网地址:数据部分逐字符完全相同,不同的只有 hrp,以及因此被改变的校验和
(naerk6 对 emzsdf)。
6. witness 版本 0 必须用 bech32,绝不能用 bech32m
目前在用的校验和有两个变体。bech32(BIP173,常量 1)用于 witness 版本 0;bech32m
(BIP350,常量 0x2bc830a3,即十进制 764559395)用于版本 1 及以上。这种配对是强制性的,
不强制检查的解码器会悄悄接受别的节点会拒绝的地址。本页的解码器会强制检查,而你可以亲眼看到它失败:
把演示地址用 bech32m 常量重新编码得到 bc1qy86hkm0telzmvuvzm76279jp7z5p3yqjxpf0nc,解码
会报错 「Witness v0 must use bech32, not bech32m」。
BIP350 之所以引入 bech32m,是因为最初的常量 1 存在插入弱点,BIP350 原文的表述是:
只要 bech32 字符串的最后一个字符是 p,在它前面紧邻位置插入或删除任意多个 q
字符都不会破坏校验和 —— 校验字符只是整体错位,于是同一个校验和可以对应长度不同的数据部分。这一点很
容易验证,本页背后的服务器就验证过:合法地址 bc1qgey9e3xtk8fpdsgchch25saytdp6nlhdt9gm0p 在那个
末尾 p 之前插入 1、2、3 个 q 之后(…gm0qp、…gm0qqp、
…gm0qqqp),校验和依然成立。在针对 bc 前缀字符串所做的 78,624 次单字符插入尝试中,
凡是校验和仍然有效的,形状全部如此,而且全部属于 bech32 —— 没有任何一个 bech32m 字符串接受了插入
的字符。
witness 版本 0 在实践中没有受到影响:v0 的程序长度被限制为恰好 20 或 32 字节,因此同时执行结构检查(补位、
程序长度)的解码器会拒绝被改动的字符串 —— 本页的解码器报的是 「Invalid padding」。演示地址本身的末位
是 6 而不是 p,这个把戏对它根本用不上。更新的 witness 版本没有这层兜底,所以 v1+
强制使用 bech32m。请永远不要自己把 bc1q 地址「升级」成另一种校验和变体 —— 两者不可互换,往手工
改动过的地址转账等于烧币。
7. P2WPKH 与它的邻居们
| P2PKH | P2SH-P2WPKH | P2WPKH(本页) | P2TR | |
|---|---|---|---|---|
| 地址前缀 | 1… | 3… | bc1q… | bc1p… |
| 编码 | Base58Check,版本字节 0x00 | Base58Check,版本字节 0x05 | bech32(BIP173) | bech32m(BIP350) |
| 承诺的值 | hash160(压缩公钥) | hash160(0014‖hash160(公钥)) | hash160(公钥) —— 即 witness 程序 | x-only 调整后的输出公钥(32 字节) |
| 输出脚本 | 76a914…88ac(25 字节) | a914…87(23 字节) | 0014…(22 字节) | 5120…(34 字节) |
| 单输入权重 | 592 WU | 364 WU | 272 WU | 230 WU |
| 签名位置 | ECDSA,在 scriptSig 里 | ECDSA,在 witness 里 | ECDSA,在 witness 里 | Schnorr(BIP340),在 witness 里 |
| 引入时间 | 2009 年,最初的客户端 | BIP49,2017 年(为兼容老钱包而包裹) | BIP141/173,2017 年 8 月 24 日激活 | BIP341/350,2021 年 11 月 14 日激活 |
| 常见于 | 老钱包、交易所、纸钱包 | 需要兼容 SegWit 之前付款方的钱包 | 新一代单密钥钱包的默认选择 | 最新钱包;唯一具备脚本路径隐私的形式 |
8. 它在推导链中的位置
- 上游:私钥 → 压缩公钥,然后是 hash160。 这里压缩公钥不是可选项。
- 同辈:P2PKH(同一个 hash160,但用 Base58Check 而非 bech32)与 P2SH-P2WPKH(把同一个程序包进 P2SH 地址)。
- 下游:P2TR / Taproot 用同一个密钥,但程序长度、校验和变体都不同, 还要对公钥做一次 tweak。
- 想把地址重新拆开看:bech32 解码页。
9. 安全须知
- 地址承诺的是公钥的哈希,而不是公钥本身。在被花费之前,公钥一直隐藏着;而一旦花费,公钥就与该地址 永久公开地绑在一起。
- 同一个地址收多笔款,会把这些付款在公开账本上串成一条线,也毁掉所有付款方的隐私。请为每笔收款派生 新地址(这正是 HD 钱包的用途)。
- 校验和防的是手误,不防有人故意替换地址。转账前在付款设备上核对开头与结尾的几个字符,并尽量用二维码 而不是手工输入。
- 地址不是秘密,但也不是所有权的证明:谁握着
k,谁就能花。不要把私钥粘贴进你不完全信任的 网页 —— 本页只在你所访问的这台主机上本地计算,不会把私钥发往任何其它地方。
10. 常见错误
- 拿非压缩公钥去哈希。 会得到另一个 20 字节程序与另一个地址,而且按 BIP143 的压缩公钥 要求根本无法花费。
- 给版本 0 用 bech32m。 所有现代钱包都会拒绝;两者的差别只是 6 个校验字符,以及原始 校验和的长度扩展弱点。
- 把分隔符当成第一个
1。 解析器必须从最后一个1处切开。 数据字符集里没有1,正是为了消除歧义。 - 手工把二维码内容改成小写。 全大写可以,大小写混用不行;只改了部分字符的转换工具会 产出一个没有任何验证器愿意接受的字符串。
- 以为「SegWit」就等于「地址以 bc1 开头」。 P2SH-P2WPKH 同样是 SegWit,但地址仍然以
3开头。
11. 速查表
| 项目 | 取值 |
|---|---|
| 地址类型 | P2WPKH,witness 版本 0,原生 SegWit |
hrp | 主网 bc,测试网 tb |
| witness 程序 | 20 字节 = hash160(压缩公钥) |
| 数据字符数 | 1 个版本字符 + 32 个程序字符(160 位 ÷ 5,无需补位) |
| 校验和 | 6 个字符,常量 1 的 BCH 码;4 个字符以内的错误必定检出 |
| 总长度 | 主网 42 个字符,全部小写 |
| 输出脚本 | OP_0 0x14 ‖ 20 字节程序(共 22 字节) |
| 大小写规则 | 全小写或全大写,绝不可混用 |