交易是怎么签名的?ECDSA 数字签名原理 图 1
交易是怎么签名的?ECDSA 数字签名原理 · 图 1

结论先说

每笔以太坊交易在广播前都要用你的私钥签名,签名是对交易内容哈希的计算结果,而不是对交易原文的加密。验证者用你的公钥(从地址推不出来,但由签名隐含验证)检查”这个签名确实出自这个私钥、且针对这组字段”。理解签名,就能理解为什么”签过的交易改一个字节就失效”、为什么跨链重放要专门防护、以及”盲签”风险从哪里来。

签名流程三步

第一步,组装交易字段:收款地址、金额、gas 上限、gas 价(或基础费+优先费)、nonce、数据(calldata)、链 ID 等,按 EIP-155/EIP-1559 规定的顺序编码成字节串。第二步,对编码结果做 Keccak-256 哈希,得到 32 字节摘要。第三步,用私钥对摘要做 ECDSA 签名,产出两个 32 字节的数(r、s)和一个恢复字节(v,早期是 recovery id,EIP-155 后编码为 chainId 相关值)。广播时发送”交易字段 + r + s + v”,任何人可以完整验证。

ECDSA 怎么工作

ECDSA 基于椭圆曲线离散对数难题。签名时:选一个临时随机数 k,用 k 和消息哈希、私钥 d 算出 r、s;验证时:用 r、s、消息哈希和公钥 Q(=d·G)做一组曲线运算,检查一致性。关键性质:改消息任何一个比特,验证必失败(哈希雪崩);没有私钥 d,无法造出能通过验证的 r、s(离散对数不可逆)。注意签名本身是公开的——链上任何人都能看到你的签名,但看不到私钥,这就是数字签名和加密的区别:签名证明”我确认过”,不保密内容。

为什么 v 里藏着 chainId

早期以太坊的签名不含链 ID,导致著名的跨链重放:同一笔已签名交易原样发到另一条兼容链(如早期的 BSC)同样有效。EIP-155 把链 ID 编码进签名计算,之后每笔签名的”有效性”绑定到特定链,跨链重放在密码学层面失效。这也是为什么钱包升级后旧格式交易的处理规则会变,以及为什么新链上线时要分配独立 chainId——不只是标识,是安全边界。

验证侧发生了什么

节点收到交易后:从 r、s、v 和交易哈希反推出签名者公钥(椭圆曲线签名恢复),再哈希成地址,检查余额足够、nonce 正确、gas 合法,才进入内存池。整个过程不接触你的私钥,任何人(包括矿工/验证者)都只能验证不能伪造。这也解释了一个常见疑问:链上怎么知道交易”是你的”?答案是签名本身携带了足够的数学证据,地址只是签名的索引标签。

盲签:签名前你到底确认了什么

钱包展示”转账 X 到 Y”时,理想情况是它先解析 calldata 再展示语义。但合约调用的 calldata 可以是任意字节:它可能包含审批(approve 无限额度)、委托、或你看不懂的操作。“盲签”风险就是指用户看到一串 0x 数据点了确认,实际授权了危险操作。防御习惯:优先用能解析合约方法的钱包和浏览器;对 approve 类操作看额度(无限授权是最大风险源);对陌生合约先查源码是否验证过、是否有社区信誉;硬件钱包的用户注意屏幕上的哈希与钱包展示是否一致(部分硬件只展示摘要)。

常见误读

“签名加密了交易内容”——没有,交易字段全网公开,签名只证明来源和完整性。“私钥签名后私钥会磨损/失效”——不会,签名是纯数学运算,可无限次使用。“同一笔交易能签两次”——不能,相同字段加相同 nonce 的签名重复广播无效(nonce 已用)。“签名能证明’当时我想这么做’“——在法律语义上不成立,密码学只证明”私钥持有者在某个时刻签了这组字段”。

风险提示

签名安全的两个根:私钥不出安全环境(硬件钱包/本地加密),签名前理解字段语义。任何”先签名再上链""签名授权客服操作”的流程都值得怀疑;对 calldata 陌生的高价值操作,宁可放弃交易也不要盲签。本文解释的是 secp256k1 + ECDSA 路线,部分新链使用不同签名方案(如 BLS),机制不同,不要直接套用。

小结

一句话记忆:交易签名 = 私钥对”字段编码的哈希”做 ECDSA,产出 r/s/v,全网可验证、不可伪造、不可抵赖,且链 ID 绑定防跨链重放。理解它,就理解了”点了确认就等于执行”这句话的全部重量。