以太坊如何从公钥一步步“炼成”地址:全流程图解与代码验证

·

当你在区块浏览器里查询“0x…”开头的地址时,有没有想过它究竟是怎样从一串看似随机的公钥字符里诞生的?本文将用通俗语言+可复现的 Node.js 脚本,带你亲手验证 公钥 → Keccak-256 → 以太坊地址 这一核心流程,彻底告别“看懂了却还是不会动手”的尴尬!

目录

  1. 关键概念速览
  2. 从公钥到地址的 5 个关键步骤
  3. Node.js 实战:10 行代码生成地址
  4. 常见问题 FAQ
  5. 常见易错点与调试技巧
  6. 延伸:如何批量或离线生成地址

1. 关键概念速览

名词中文作用
ECDSA-secp256k1椭圆曲线数字签名算法由私钥推导非压缩公钥
非压缩公钥65 字节数据 (0x04 + X 坐标 32 字节 + Y 坐标 32 字节)地址推导的原材料
Keccak-256哈希函数以太坊的“SHA-3”,生成 32 字节哈希
EIP-55 校验地址大小写混合规则防输入错误

2. 从公钥到地址的 5 个关键步骤

核心关键词:以太坊地址生成、公钥哈希、Keccak-256、校验地址、EIP-55
  1. 取公钥主体:去掉前缀 04(若带 0x 则去掉前 4 字符 0x04)。
  2. Hex → Bytes:把剩余 128 个十六进制字符转为字节数组(64 字节)。
  3. Keccak-256:对字节数组做 Keccak-256,得到 64 字符的十六进制哈希。
  4. 截取后 40 位:取该哈希的后 40 个字符(20 字节),加上 0x 即原始地址。
  5. EIP-55 校验:根据哈希结果大小写化地址,防手工输入错误。

3. Node.js 实战:10 行代码生成地址

以下脚本仅需 ethersjs-sha3,即可一键验证全流程。👇

// test.js
const { ethers } = require('ethers');
const keccak = require('js-sha3').keccak_256;

const pk = '18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725';
const wallet = new ethers.Wallet(pk);

// 1. 非压缩公钥:0x + 04(x)+64(y)
const pub = wallet.publicKey;

// 2. 去掉04再转为字节数组
const pubBytes = ethers.utils.arrayify('0x' + pub.slice(4));

// 3. Keccak-256
const hash = keccak(pubBytes);

// 4. 取后40字符
const rawAddress = '0x' + hash.slice(-40);

// 5. EIP-55 校验
const checksumAddress = ethers.utils.getAddress(rawAddress);

console.log('非压缩公钥:', pub);
console.log('最终校验地址:', checksumAddress);
console.log('与 wallet.address 一致?', checksumAddress === wallet.address);

运行输出示例(你已可复现):

非压缩公钥: 0x0450863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b23522cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6
最终校验地址: 0x3E9003153d9A39D3f57B126b0c38513D5e289c3E
与 wallet.address 一致? true

👉 点击查看在线体验脚本,直接执行即可查看结果


4. 常见问题 FAQ {#常见问题 FAQ}

Q1:用压缩公钥(33 字节)也能推地址吗?
A:可以。ethers 会自动识别公钥格式,并先做解压缩,再按相同流程计算地址。

Q2:为何我手动截 40 位还是得不到正确地址?
A:多半是在第 2 步没有将十六进制字符串转为字节数组就扔进 Keccak-256,导致哈希结果和官方库不符。

Q3:主网、测试网地址格式有差别吗?
A:地址本身无差别,前缀一律为 0x;差异仅在链 ID 与签名端点,不影响地址生成逻辑。

Q4:地址可以反向得到公钥吗?
A:无法。Keccak-256 具有不可逆与抗碰撞性,理论上无法从 20 字节地址复原原 64 字节公钥。

Q5:钱包助记词与地址的对应关系?
A:助记词派生私钥(BIP-39/44),再由私钥派生公钥与地址。单向树状推导,同一助记词可派生无数地址。

Q6:多签/智能合约地址如何生成?
A:合约地址 = keccak256(rlp([sender, nonce]))[12:];多签地址其实就是合约地址的另一种呈现,同样符合 EIP-55 规则。


5. 易错点与调试技巧

👉 用互动沙箱调试这段代码,5 分钟验证成功


6. 延伸:批量或离线生成地址

  1. 批量生成:配合 ethers.Wallet.createRandom(),循环 10,000 次即可冷钱包离线生产地址列表。
  2. 离线环境:拔掉网线 + 关闭 Wi-Fi,在本地跑脚本,再手动抄写 privateKey → 地址对。
  3. 安全备份:组合硬件钱包 Ledger + 金属助记词板,实现防火防水长期保存。
关键词提示:以太坊地址批量生成、离线冷钱包、助记词备份、硬件钱包安全

如你遵循以上步骤,就能从最底层的 65 字节非压缩公钥,“零信任验证”地得到一个合乎 EIP-55 的以太坊地址。动手跑一次脚本,比看十篇博客更管用,祝你掘密顺利!