很多人第一次接触以太坊开发时,最先记住的就是私钥、公钥、地址这三个词,但也常常被它们绕晕。我见过不少朋友把地址当成“账户ID”,却说不清地址背后其实只是一段公钥哈希;也有人手里握着私钥,却不知道它和公钥之间到底是怎么做数学变换的。这篇文章想把这整条链路讲透:从私钥如何通过椭圆曲线乘法变成公钥,再经过 Keccak-256 哈希变成地址,最后落到工程上如何用代码实现、如何安全存储、如何避开那些日常开发里最隐蔽的坑。不管你是刚入门写合约,还是已经在做钱包、DApp 周边工具,这条链路都是避不开的地基。
1. 一条私钥怎么变成地址?先看懂整条推导关系
1.1 三个概念的本质区别
先给三个词做个最直白的定义。
私钥,本质上是一个 256 位的随机整数,范围必须在 1 到 secp256k1 曲线的阶 n-1 之间。谁拥有私钥,谁就拥有对对应地址资产的完全控制权。私钥可以签名交易,签名之后全网任何人都能验证这笔交易“确实由私钥持有者发出”。
公钥,是由私钥在 secp256k1 椭圆曲线上做标量乘法得到的。它是一个椭圆曲线上的点,由 32 字节的 X 坐标和 32 字节的 Y 坐标组成。公钥可以公开,因为从公钥反推私钥在计算上不可行,这就是椭圆曲线离散对数难题。
地址,则是公钥做一次 Keccak-256 哈希,再取结果后 20 字节得到的。地址用于接收资产、作为合约调用方标识,但它不是“完整账户”,只是公钥的“指纹”。
很多入门资料喜欢拿“钥匙、锁、门牌号”做类比,我个人觉得更贴切的是“印章、印泥验证、印章编号”。私钥像一枚私章,签名就是用这枚章盖下去;公钥是用来验证这个章印是否出自你手里的章;地址则是在这个章面上刻的一串编号,别人只需要拿着编号就能找到你,但拿到编号并不能伪造你的章。
1.2 推导链路与单向性
整条链路可以用一行公式写清楚:
text复制私钥(n) → 公钥(Q = n·G) → 地址 = Keccak-256(Q_x || Q_y) 的后 20 字节
每一步都是单向的。也就是说:知道私钥,可以算公钥,也可以算地址;知道公钥,可以算地址;但知道地址,不能反推出公钥,更不能反推出私钥。除非某个地址曾经发起过交易,交易签名里会携带 v, r, s,这组数据可以恢复出公钥,但恢复公钥依然不能反推私钥。
这里要特别强调一点:地址不是私钥的加密结果,而是密钥的“摘要”。正因为如此,地址偶尔被碰撞的概率虽然低到接近零,但在理论上存在两个私钥映射到同一地址的可能性。工程上我们一般直接忽略这个概率,因为 secp256k1 的私钥空间是 2^256 量级,发生碰撞的概率比连续买中两次头奖还低太多。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 动手前必读:椭圆曲线、哈希函数与以太坊的选型逻辑
2.1 secp256k1 参数与群运算
以太坊没有使用 RSA 或普通离散对数,而是选择了椭圆曲线密码学。具体参数是一条名为 secp256k1 的曲线,它由比特币社区推广,后来被以太坊沿用。这条曲线定义非常简单:
text复制y² = x³ + 7 (mod p)
其中 p 是一个超大素数。所有运算都在有限域上完成,不是实数域,所以曲线上的点相加有自己的一套几何规则。私钥 n 与基点 G 做标量乘法,得到的就是公钥点 Q:
text复制Q = n · G
这里的“·”不是普通乘法,是椭圆曲线上的重复点加法。虽然我们从公式上写的是乘法,但实际运算过程是不断做点加和点倍。核心参数我整理了一张表,方便你查阅:
| 参数 | 值 |
|---|---|
| 曲线方程 | y² = x³ + 7 |
| 有限域 p | 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F |
| 基点 G 的 X | 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798 |
| 基点 G 的 Y | 0x483ADA7726A3C4655DA4FB |
