前言

在区块链安全领域,有两种攻击名字经常一起出现:

重放攻击
双花攻击

很多文章会直接甩定义,但真正做系统时你会发现:

它们看起来很像

本质却完全不同

防御手段也完全不一样

这篇文章,我们不背概念,直接从“钱是怎么被花掉的”讲起。

一、先用一句话区分它们

攻击类型 核心问题
重放攻击 同一笔“合法签名”的交易,被重复利用
双花攻击 同一笔钱,被花了两次

👉 关键差异:

重放攻击:签名被重复用

双花攻击:余额被重复花

二、从交易本质开始:区块链到底在验证什么?

区块链对一笔交易,最核心只验证三件事:

签名是否正确(是不是你签的)

交易是否唯一(有没有被处理过)

余额是否足够(钱还在不在)

这三点,正好对应:

重放攻击 → 利用 1 + 2 的漏洞

双花攻击 → 利用 2 + 3 的漏洞

三、重放攻击(Replay Attack):签名没问题,但被“重复用”

1️⃣ 什么是重放攻击?

重放攻击的核心是:

攻击者拿到一笔“已经签过名的合法交易”,在另一个场景再次使用

注意这句话的重点:

签名是 真的

不是伪造

只是 重复使用

2️⃣ 一个最经典的重放攻击场景
场景:链 A 和 链 B 参数完全一样

用户在 链 A 上签了一笔转账

攻击者拿到了这笔交易数据

把同样的交易广播到 链 B

链 B 验证通过,交易生效

结果:

用户在 没意识到的情况下,在两条链都转了钱

这在早期 ETH / ETC 分叉 时是真实发生过的。

3️⃣ 重放攻击的“技术根因”

本质只有一句话:

签名没有绑定“唯一上下文”

具体表现为:

没有 chainId

没有 nonce / sequence

没有 domain separation

于是:

同一个签名,在多个环境下都成立

4️⃣ 常见的重放攻击类型
类型 说明
跨链重放 同一签名在不同链生效
合约重放 同一 calldata 多次调用
授权重放 approve / permit 被反复利用
5️⃣ 如何防御重放攻击?

一句话原则:

让每一次签名,只能在一个场景下生效一次

常见手段:

chainId(EIP-155)

nonce / sequence

时间戳 + 过期机制

domain hash(EIP-712)

四、双花攻击(Double Spend):钱被花了两次

1️⃣ 什么是双花攻击?

双花攻击指的是:

同一笔资产,在系统中被成功支付了两次

这不是签名问题,而是共识与确认问题。

2️⃣ 一个典型的双花攻击过程(UTXO 视角)

攻击者有 1 BTC

同时构造两笔交易:

Tx1:付给商家

Tx2:付给自己

把 Tx1 发给商家

把 Tx2 广播到网络

如果:

商家未等待确认

或攻击者算力足够

就可能出现:

商家交付了商品
但最终链上只确认了 Tx2

3️⃣ 为什么双花在 PoW / PoS 下还能发生?

因为区块链有一个现实前提:

最终一致,而不是瞬时一致

在“未最终确认”前:

分叉是可能的

状态是可回滚的

双花,本质就是在这个时间窗口里做文章。

4️⃣ 双花攻击的常见形式
类型 说明
0 确认双花 商家不等确认
分叉双花 利用链重组
51% 攻击 控制多数算力/权益
自私挖矿 操纵出块顺序
5️⃣ 如何防御双花攻击?

原则只有一句:

别相信“未最终确认”的交易

常见做法:

等足够区块确认

大额交易延长确认数

使用 finality(PoS)

链下先冻结、链上后结算

五、重放 vs 双花:一次性对比清楚

对比项 重放攻击 双花攻击
利用点 签名可复用 共识未稳定
是否需要算力 ❌ ✅(通常)
是否链内发生 不一定 是
防御重点 nonce / chainId 确认数 / 共识
更偏哪层 应用 / 协议 共识层
六、对后端 / 交易所 / 钱包的真实建议
1️⃣ 钱包系统

每笔签名必须有 nonce

跨链操作强制 chainId

授权操作必须可撤销

2️⃣ 交易所 / 充值系统

充值不上账前,等足确认

不用 mempool 交易当“成功”

严禁 0 确认入账

3️⃣ 合约设计

防重放 ≠ 防重入(别搞混)

签名消息必须 domain 分离

permit 一定要校验 nonce

七、结尾:一句“老工程师才会说的话”

重放攻击,是“你签得太随意”
双花攻击,是“你信得太着急”

区块链安全,99% 的坑不在密码学,而在:

边界没想清

时序没想清

假设过于乐观

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐