压缩公钥是什么?02与03开头的33字节怎么顶替65字节 图 1
压缩公钥是什么?02与03开头的33字节怎么顶替65字节 · 图 1

导入过早期钱包的人大多见过这个提示:压缩公钥还是非压缩公钥,选错地址就对不上。为什么同一个密钥有两种长度?这不是什么加密机关,而是一道把坐标写省了的记账题。

曲线上的点:公钥到底是什么

比特币与以太坊用的椭圆曲线 secp256k1,核心是一条方程 y² = x³ + 7 在素数域上的解集,加上一个固定起点 G。公钥的本质是私钥 d 乘以 G 得到的曲线上的点,也就是一个坐标对 (x, y)。两个坐标各自约32字节,完整写下来64字节,再加一个格式标记就是常见的65字节公钥:前缀 0x04,后面依次是 x 与 y。

关键性质藏在方程里:给定 x,方程右边 x³ + 7 就定了,y 是某个数的平方根。在素数域上,平方根要么不存在,要么恰好两个解,而这两个解关于 p 互补,必然一奇一偶。换句话说,y 虽然要32字节来写,但信息量只有一位:知道 x,再知道“y 是奇还是偶”,y 本身可以当场算回来。省掉坐标、保留奇偶性,就是压缩的全部思想。

33 字节:前缀一个字节,横坐标32个字节

压缩格式因此是:前缀 0x02 表示 y 为偶,0x03 表示 y 为奇,后接32字节的 x。任何看到 02/03 开头的33字节的程序,都能一步解出完整坐标,验证签名、推导脚本都毫无损失——它和被压缩前的点在数学上是同一个对象。历史上还出现过 0x06/0x07 开头的混合格式,同时携带奇偶位和完整 y,纯属兼容产物,如今几乎见不到。要强调一点:这里没有任何“可解压的秘密”,65字节到33字节不是压缩算法意义上的数据压缩,只是少写了一个可以重算的量,不涉及任何压缩率、字典或质量损失。

为什么两种格式会哈希出两个地址

比特币地址来自对公钥序列化结果做哈希(比如先 SHA-256 再 RIPEMD-160)。哈希函数不认识“数学上同一个点”,它只吃字节串:65字节的串和33字节的串内容不同,哈希自然不同,于是同一个密钥确实能产生两个合法地址,各自的 UTXO 互不相干。早年的钱包把这一点直接摆到用户面前当选项,选错就表现为“导入后余额不见了”,其实是钱躺在另一种格式的地址上。今天的默认实践几乎全面转向压缩格式,新建钱包很少再让用户二选一,但恢复十几年前的老钱包时仍可能撞上这个问题:老地址若是非压缩公钥生成的,用只支持压缩派生的新工具扫描就会漏地址,这属于恢复流程里值得专门检查的一格。

再省一格:BIP-340 的 32 字节 x-only 公钥

2021年随 Taproot 软分叉激活的 BIP-340 更进一步:签名方案直接规定公钥只写 x 坐标,整整32字节,不再带任何前缀;约定遇到奇数 y 的点就取其互补点代替,签名算法对此有明确处理。这套设计与 Schnorr 签名的内部数学(提升操作 lift_x)配套,把“同一个点两种写法”的分叉从协议层抹平:既然奇偶性不再需要携带,也就不再产生两套地址的歧义。换句话说,压缩公钥解决的是“少传一半坐标”,BIP-340 解决的是“让格式只有一种真相”。理解这条演化线,比背下前缀对照表更有用:协议对密钥序列化的每一次修订,都是在减少可选写法,而不是增加魔法。

三条实用提醒

第一,公钥可以公开,压缩与否都不泄露私钥:从 x 反推 d 依然是离散对数难题,省坐标省不掉数学难度。第二,看到 02/03/04 开头的长十六进制串,先数长度:33字节压缩、65字节非压缩、32字节 x-only,三者都可能是合法公钥,别按“短就是残缺”处理。第三,做备份或多签配置时,同一组密钥在不同工具里显示的格式可能不同,这是显示层差异,不代表私钥变了;核对身份请核对地址或指纹串,而不是原始十六进制。理解公钥格式不涉及任何收益或价格判断,本文仅为密码学概念科普,不构成投资建议。