本文作者Peter Todd受Kruw项目委托,分析了Yuval Kogman对中心化CoinJoin的去匿名化攻击的讨论,重点关注Wasabi钱包使用的WabiSabi协议。
作者:Peter Todd
来源: https://petertodd.org/2025/coinjoin-comparison
原文出版于 2025 年 7 月。
Kruw 项目请我分析和回应 Yuval “nothingmuch” Kogman 讨论中心化的、基于回合的去匿名化攻击的帖子 1,尤其是 2 对 Wasabi 钱包所用的 WabiSabi 协议的攻击。Kogman 曾经参与 WabiSabi 的设计,但 “在它发布之前就以离开以示抗议” 1。
Kogman 声称,“这套软件根本就不适合于其设计目标;如果你不愿意把你的隐私信息交托给协调员,就不该使用它”。但是,Kongman 并没有为这项意见提供一个清晰的工程基础。所以我认为,对 coinjoin 的特性、其防止的攻击以及当前两大 coinjoin 实现 —— Joinmarket 和 Wasabi —— 能否防范真实世界的去匿名化攻击,作一番安全分析,是有价值的。
免责声明:Kruw 以我平时的开源活动咨询价格为我的调查时间付了费;他们运行着 最受欢迎的 Wasabi 协调员。我个人也使用 Wasabi,并且实际上,我正是从 Kruw 的 Wasabi 钱包收到跟这篇文章有关的支付的。
“Coinjoin” 这个概念最早因为 Gregory Maxwell 在 2013 年的文章而变得广为人知 3。基本原理不复杂:如果有两个乃至更多人一起创建一笔比特币交易,“ 输入所有权同一性” 启发式分析便会被击败,因为这笔交易的所有输入事实上并非都属于同一个人。构造 coinjoin 交易最简单的方式便是让已经有支付意愿的两方乃至多方将他们各自的交易中的输入和输出直接集中到一笔交易中。哪怕是这种简单的方式,也能获得少量的成本节约:各方将共享交易 “头” 中的字节,从而总体上的交易费用降低。
然而,这种简单技术会因为两个重要原因而损失隐私性:
比如说,考虑这样一笔交易:
| 输入(金额) | 输出(金额) |
|---|---|
| 61, 836 | 53,467 |
| 98, 902 | 61, 736 |
| 45, 235 |
如果你怀疑这是一笔非常简单的两方 coinjoin 交易,那么可以合理猜测第一个输入和第二个输出是同一个人的,而第二个输入中的资金则进入了第一个和第三个输出。
上述分析使我们得出了两种主要的威胁模型:
有趣的是,根据我跟 Chainalysis 及其竞争公司的在职和离职员工的私下交流,真实世界里的区块链分析实际上不屑于运行哪怕是去匿名化最简单的 coinjoin 交易这种程度的统计学分析。实际上,他们根本不屑于运行任何合理的统计学分析:他们的产品是非常不科学的,并且基于本质上是直觉和原始的启发式分析来给输出 “打标签”,而不是实际上搞清楚给定的一个输出与某一个活动相关的概率 5。我甚至遇到过一家 Chainalysis 的竞争对手的以为创始人,在晚餐后醉醺醺地跟我说他的产品完全就是一个骗局,完全不作任何真正的分析:他的产品的真正目的是给警察抓人提供借口,以及让交易所能够满足 “AML/KYC” 的检查要求。Chainlysis 自己也一直在极力隐藏他们的产品的真实运作方式,比如,在法庭上;很有可能 Chainlysis 的产品事实上也无法可靠地工作。
保守地看, 最近的法庭文件 披露了 Chainalysis 运行了一个 Tornado Cash 的转发器,可以假设是尝试收集 Tornado Cash 用户的数据。虽然 Tornado Cash 是跟 coinjoin 非常不同的技术,但如果 Chainalysis 正在采取主动方法来去匿名化 Tornado Cash 的用户,他们可能也在采取主动用法来去匿名化 coinjoin 的实现。
(译者注:“Tornado Cash” 是一种运行在以太坊区块链上的隐私强化服务;其原理是用户们存入标准化数额的资金,在一段时间后以不记名的凭证从资金池中取出资金。)
不论如何,不管我们的敌手现在是不是骗子,我们都应该假定他们是真的有能力。
隐私工具通常以 “k-匿名集” 的属于来分析:由 $k$ 个个体组成的集合,这些个体都是匿名的、与集合中的其他人不可分辨。Coinjoin 这样的货币应用额外加入了一个元素:你的资金来源的资金数额。这是特别关键的,如果你尝试 coinjoin 较大额度的资金的话:更大金额的 k-匿名集 会更小,因为更少人有足够多的资金成为这个匿名集的潜在人选。
Tor 网络是一个 洋葱路由 网络。Coinjoin 方案使用 Tor 来形成匿名性:只要 Tor 节点遵守了自己的承诺(不保存日志),那么在最严苛的威胁模型中,Tor 也允许 coinjoin 的客户端匿名地通信;这对 JoinMarket 的安全模式是重要的,对 Wasabi 的安全模式则是极为关键的。
Tor 并不是 去中心化的。虽然大量志愿者们在运行个人 Tor 节点,Tor 共识自身 —— Tor 节点的列表 —— 是由一组中心化的 “ 目录权威” 来维护的,他们可以独自决定谁算或不算是一个 Tor 节点。
只有三种重要的 coinjoin 方案是真正被实现了且当前正在运作的。它们中的每一种都使用了完全不同的方法,各有优缺点。
这是一种两方的 协议,允许一个支付者(发送者)与一个收款者(接收者)创建一笔 coinjoin 交易,包含他们各自已经有意愿发送的支付。这样的交易可以击败输入所有权同一性启发式分析,因为它将支付方和收款方的钱币都放在交易中。因为 payjoin 是一种协议,许多钱包都已经支持了它,包括我们接下来要讨论的另外两种 coinjoin 实现:JoinMarket 和 Wasabi 。
Bull Bitcoin 手机钱包 是展现 payjoin 何以、何时会带来好处的好例子。该钱包由 Bull Bitcoin 交易所 开发,致力于解决两个关键问题:
交易所的客户在购买比特币时,每次购买都会形成一个 UTXO 。Payjoin 则让以前买到的 UTXO 可以跟最新买到的 BTC 合并,结果是,日后花费时,只需为交易提供一个输入(也即归集后的 UTXO),因此手续费更少,而且不影响隐私性。
在卖出比特币时,coinjoin 交易可以通过合并一个乃至更多已有的 UTXO(跟当前卖出的 UTXO 结合)来节约交易所的手续费。此外,在未来,payjoin 将让 支付 cut-through 成为可能,可以进一步节约手续费。而且显然,双方都能从扩大的 k-匿名集中获得潜在的好处。
(译者注:“cut-through” 的意思是不论交易过程有多复杂,最终只发布初始状态和终局状态。比如 n 个互有部分支付需要的个体共同参与一笔交易的创建,最终交易的输出是各方结算之后的终局状态,过程中的谈判顺序和细节都不会以交易的形式暴露出来。)
因为 payjoin 是一种两方协议,主动攻击就无关紧要了:与你 payjoin 的另一方一定知道交易的哪个输入和输出属于你。而且,女巫攻击也失去意义:不管怎么说,你是在跟一个你本来就想与之交易的人 payjoin 。
在现实中,payjoin 交易通常是可以识别的,基于 “ 不必要输入” 启发式分析,也就是假设钱包软件只会提供足以执行一笔支付的最少数量的输入,从而猜测出支付方和收款方。这种假设 并不必然 是正确的,因为一些钱包真的会为了 UTXO 管理和隐私性而加入不必要的输入。其次,也不是所有的 payjoin 交易都能用这种分析。 交易模式的区别,比如,比特币交易所和典型的比特币囤币者的去壳,可能足以将双方的输入和输出辨识出来。不过,payjoin 的手续费节约足以成为所有链内钱包支持它的理由。
我们不会再讨论了 payjoin 了,因为它为所有链内钱包提供了显然的削减手续费的好处 —— 也包括 coinjoin 钱包 —— 而没有显著的缺点(除了实现上的复杂性)。如果你希望在链内支付的对象提供了 coinjoin 的选项,那么没有理由 不使用 payjoin 。
该协议致力于成为一个 吃单人-挂单人 协议,其中 吃单人 给一个乃至更多 挂单人 支付来提高自身的交易隐私性,办法是让挂单人也贡献自己的输入和输出到交易中(他们可以获得支付);吃单人也负责支付交易手续费。
如果挂单人贡献的是随意(价值)的输入和输出,那就无法提供任何隐私性提升,因为挂单人和吃单人的输入可以很容易通过金额的匹配而识别出来。所以,相反,挂单人要贡献跟吃单人的支付输出 价值相等 的输出。这背后的想法是,通过让一笔交易拥有多个相同面额的支付输出,我们就能得到一个包含这些输出的一个 k-匿名集。
以下是 JoinMarket 交易的一个非常简单的例子,是我为这笔交易而制作的,只有一个吃单人和一个挂单人,交易 ID 为 “ 4f11…8b7d”:
| 输入(数额) | 输出(数额) |
|---|---|
| 148,798 | 46,981 |
| 1,448,113 | 100,420 |
| 1,347,800 | |
| 100,420 |
乍看起来,这个价值 100, 420 聪的输出拥有一个 $k = 2$ 的匿名集:这笔输出有两个这样的输出。但假设你是第一个 100, 420 聪的输出的 收款方 。那么考考 你,这的这笔钱是从哪里来的?根据 JoinMarket 的工作原理,可以合理假设我是给你支付的吃单人,而交易的另一个参与者是挂单人。因为我必然是吃单人,所以我必须为这笔交易支付手续费,还要给挂单人支付费用。
有了这个假设,你可以轻松将我的输入去匿名化 —— 通过合理猜测哪个输入跟哪个找零输出相匹配;只需一些简单的算术:
$$
\begin{align}
148798 - 100420 - 46981 &= 1397 \
1448113 - 100420 - 1347800 &= -107
\end{align}
$$
显然,第一个输入来自吃单人,因为它为交易贡献了 1397 聪的净价值,而第二个输入则收到了 107 聪的挂单人手续费。由于制作交易的人是我自己,所以我可以确认这是正确的。
即使我支付了 107 聪的挂单人手续费,并支付了 698 聪的区块确认手续费,我还是没有获得更多的隐私性!
这个问题并不是我们这笔简单的测试交易独有的。在绝大部分情况下,即使使用了多个挂单人,吃单人还是可以用这种分析识别出来。问题的根源在于,JoinMarekt 是一种市场(market):吃单人和挂单人拥有完全不同的角色,因此,他们的输入和输出就可以根据 “吃单人要给挂单人付钱” 这个事实辨别出来。
从一定意义上说,JoinMarket 的经济机制完全是倒退:在一种典型的情形下 —— 吃单人给多个挂单人付费 —— 挂单人也许能够因为诱饵输出拥有所有挂单人组成的 k-匿名集而获得隐私性改进 6。而吃单人 —— 为这项服务支付不少费用的人 —— 通常不能获得隐私性好处。
在我开始撰写这篇文章的时候,我还没有注意到这个问题。但事后发现,早在几乎十年前,这个问题就已经在 bitcointalk 论坛上得到了具体的讨论,那时候还是 JoinMarket 初次发行后不久。然而,它的重要性似乎没有得到充分的重视。
虽然 JoinMarket 的其它方面可能还有有趣之处 —— 比如它使用了忠诚保险(fidelity bonds)以应对女巫攻击 —— 它的主要功能并不能满足预期。所以我们在后文中也不会再关注它;我并不推荐使用 JoinMarket,除非它重新设计。
WabiSabi 协议 是一种多步骤的 coinjoin 协议,由 Wasabi 钱包 实现 7。还有一种使用 WabiSabi 协议的 BTCPay Server 插件,但它已不再维护了。除了 Wasabi 钱包,我不知道还有别的 WabiSabi 实现,所以,在这篇文章中,我将用 “Wasabi” 来指称这条协议和 Wasabi 钱包实现。最后,虽然 Wasabi 钱包以前有一个 1.x 版本,但现在已经被弃用了,所以我们仅仅指的是它当前的 2.x 版本。
Wasabi 依赖于数额分解以在多个用户之间实现一个 k-匿名集。存入 Wasabi 的资金的隐私性,受到一个或多个 coinjoin 回合 的保护,而一个(用户指定的)中心化的协调员会协调多个用户来 coinjoin 他们的资金。
为撰写这篇文章,我创建了一个新的 Wasabi 钱包,并存入了 516, 237 聪。然后,我允许使用 Wasabi 使用 https://coinjoin.kruw.io/ 协调员来 coinjoin 这些资金,使用 “最快速度” coinjoin 策略。这里是我参与第一个 coinjoin 回合的输入和输出,交易 ID 为 “ 7a27…47ad”:

为了实现一个 k-匿名集,我的 Wasabi 钱包将存入的金额 解耦 为多个标准化面额的输出 8,并让它分散在参与同一 coinjoin 回合的其他参与者之间。比如说,我的面值为 59, 049 聪的输出,就是该交易的 5 个不同的价值 59, 049 聪的输出之一,这就形成了大约是 5 的 k-匿名集;而我的价值 100, 000 聪的输出,是 14 个这样的输出之一,也就是位于大概是 14 的 k-匿名集中。
你可能也注意到了,表示输出的条目左边有个盾牌,盾牌旁边有个数字。Wasabi 会跟踪每一个 UTXO 的 “ 匿名分数”。它度量的是 Wasabi 认为每一 coinjoin 回合可以提供的 k-匿名集的大概大小 —— 并不绝对准确。你可以在 Wasabi 中为你的钱币配置匿名分数目标,然后 Wasabi 会持续运行 coinjoin 回合,直到你所有的(可以经济地花费的)钱币都达到你的目标。在这个测试钱包中,Wasabi 总共运行了三轮 coinjoin,使所有的输出都达到了目标。

重要的是,匿名集分数会考虑其他参与者的总价值投入和输出构成。比如,在交易 ef4a…62d3 中,我故意使用了一个不那么热门的协调员 —— 参与的用户更少。因为缺乏其他参与者,Wasabi 将我的输出的匿名分数计算为 1 。

因为 Wasabi 使用了中心化的协调员,只要你使用的是热门的协调员,实现非常大的 coinjoin 交易(带有几百个输入和输出)就是比较直接地,绝大部分面额都会有十多个看起来一模一样地输出。在这种情况下,只要相对较少地手续费,就能实现相对较大的匿名集,所以 Wasabi 的成本效率是相当高的。与 JoinMarket 不同,因为所有参与者(除了协调员自身)都是平等参与的,没有(已知的)方法能实现被动区块链分析攻击 ——以超过 k-匿名集内生的概率,匹配输入和输出。
2.3.1 回合的结构与密码学
使用一个中心化协调员,实现上述一切功能的一种方法是直接让每一个参与者都告诉协调员自己希望在 coinjoin 中使用什么输入和输出,然后,协调员可以构造出一笔交易,包含所有请求的输入和输出,让参与者们签名。如果 Wasabi 是这样工作的,那么最终的 coinjoin 交易将能抵抗被动的区块链分析。其次 —— 假设每一回合都有大量的参与者 —— 那么一个参与者通过排除法来知道哪个输入和输出属于 其他哪个 参与者就很难了。
但是,你必须信任协调员会保守秘密(输入与输出的关联)。这就是问题。两方面都有明显的理由:不仅我们更希望协调员不知道这个秘密,诚实的协调员也更希望自己压根不知道这个秘密。
Wasabi 通过一个多阶段的协议来缓解这个问题:参与者们通过一个匿名的通信机制(比如 Tor)来使用多个身份。想获得完整的描述,你可以阅读 这个说明书。但我会总结为如下四个阶段:
在这里,隐私性的保证是在输入登记和输出登记阶段使用两个不同的身份(集合),以及使用各回合专属的类似于 ecash 的 token 。对抗协调员主动分析的隐私性保证重度依赖于 Tor:如果 Tor 连接可以被协调员去匿名化,协调员就能将输入和输出关联起来。
出于本文的目的,我们会假设 Wasabi 所用的类似于 e-cash 的 token 的底层密码学得到了正确实现并且被正确使用;我还不知道有人说过这个假设不能成立。相应地,我们会更加深入协调员盲化的多方 coinjoin 方案的安全模式的细节,以及 Kogman 对 Wasabi 的批评。
如果协调员无法关联输入和输出,上述 coinjoin 方案能去匿名化吗?当然!可以使用一种 “ 女巫攻击”:如果一个主动攻击者可以成功用大量的参与者身份 “冲垮” 一个 coinjoin 回合、使得这个 coinjoin 回合只有攻击目标是真实用户(其余 每一个 参与者都是攻击者控制的),攻击者就能通过一个简单的排除法来去匿名化这次 coinjoin 回合。
这种攻击对于任何类型的多方开放式 —— 任何人都能成为参与者,并且可以匿名参与的 —— coinjoin 系统来说都是根本性的 9。实际上,这种攻击甚至能 —— 在理论上 —— 应用在门罗(Monero)和 Zcash 这样的系统中。唯一的问题在于,这样的攻击有多昂贵?
一笔典型的 Wasabi 回合交易 10,使用 Kruw 协调员,其体积大概是 25000vB,要支付大概 50000 聪的手续费。以当前的汇率计算,大概是 50 美元。此外,Wasabi 每天都会运行数十个 coinjoin 回合。
敌手如果想尝试一种直接的女巫攻击,用许多输入和输出来冲垮每一个 coinjoin 回合、孤立受害者,那么可能每天都要在手续费上花费几千甚至几万美元。此外,因为通常来说,每一回合都有价值数百万美元的 BTC 被 coinjoin,所以令人信服的攻击还需要先获得价值数百万美元的 BTC 来模拟。
没有证据表明这样的攻击正在发生。当然,没有政府或其他实体公开声称正在运行这样的攻击;并且,在我跟参与区块链分析行业的人的私下交流中,我也完全没有听到有关于这样的攻击的说法。
讽刺的是,如果真的有这样的攻击,可以说它会 提升 并非攻击目标的 coinjoin 参与者的隐私性(至少暂时会)。这意味着一些实体花费了大量资源来运行 coinjoin,只是为了把数据留给自己(至少暂时是这样)。
那么女巫攻击可以便宜一些吗?如果有协调员的参与,也许可以。在这一节,我们假设回合一致性(consistency)保持不变;下一节我们再讨论回合一致性无法成立的情形。
(译者注:此处的 “一致性” 应该使用的是分布式系统领域的含义:在整个过程结束后,所有参与者能得到相同的结果。)
任何多方 coinjoin 方案都将使用一些类型的输入登记机制,以及某种类型的 “回合”。如果一个攻击者 —— 包括协调员自身 —— 可以引导不同的用户参与不同的回合,那么攻击者发动女巫攻击就会便宜得多。比如说,假设一个攻击者一直在尝试跟踪一组钱币(其中包含一个或多个钱币),直到这组钱币进入了 coinjoin:与其女巫攻击所有的 coinjoin 回合,不如仅仅攻击花费这些钱币的 coinjoin 回合。
在 Wasabi 中, 没有 协调员的串通的话,攻击者只能反复尝试加入一个又一个 coinjoin 回合,然后在发现该回合不包含目标输入之后断开连接。由于 Wasabi 使用了黑名单机制,这种攻击要准备大量的钱币,因为每加入一个无法实施攻击的回合,都会导致一些钱币被加入黑名、无法用于后续的回合。
因为一笔 Wasabi 交易是非常昂贵的,这种攻击即使能成功也要付出高昂的代价:在上述我的交易中,一个女巫攻击者若要孤立我,依然必须付出价值 140 美元的手续费,才能去匿名化我;并且,TA 还必须先能够支配许多组价值 100 万美元的 BTC(以参与 coinjoin 回合)。
此外,这种攻击还有一种内在的取舍,在获得的信息和 干扰性/侦测简易性 之间:如果攻击一直成功地运行女巫攻击,以至于各个回合都只剩一位其他用户(真实用户),那么攻击者将摧毁这个协调员处的所有 coinjoin 活动。这就非常可疑!反过来,如果花费非目标钱币的回合也能成功,那又意味着花费 目标 钱币的回合也将包含 非目标 钱包,这就减少了从这种攻击中获得的信息。
有了 协调员的配合,这种攻击所需的资本量就少得多,而且可以更成功。首先,先假设该攻击者知道该目标想要 coinjoin 的 所有 钱币 11。
攻击者参与每一个回合,将自己的女巫钱币登记为输入。如果其他参与者登记了 非目标 的钱币,攻击者就退出,导致没有女巫钱币的归责回合。因为攻击者跟协调员有 “合作”,这些女巫钱币 不会 被打入黑名单,所以可以重复使用。
如果其他参与者登记了 目标 钱币,协调员就阻止(女巫钱币之外的) 非目标 钱币参与同一回合。从非攻击目标参与者的角度处,这看起来只是协调员出了临时故障。要么是目标钱币在第一时间注册了,从而产生了一个 “成功” 的回合;要么,(如果先有非目标钱币加入)在一个归责回合之后,coinjoin 成功。不论是哪一种情况,最终的交易都只有女巫攻击者和目标,从而可以轻松去匿名化。
这种攻击,如果要形成一次令人信服的 coinjoin 回合,依然是昂贵的:攻击者依然要为自己的输入和输出支付交易手续费。但可以用少得多的可支配资金来完成,因为黑名单不再是障碍;如果黑名单可以向其他参与者公开,检测这种与恶意协调员串通的攻击会更容易。
理想情况下,绝对不该重复使用地址。与几乎所有钱包软件一样,Wasabi 使用了一种 确定性钱包 模式:地址是从一个种子确定性地生成出来的。然而,问题在于 “ 空地址限制”:在从一个种子复原一个钱包时,钱包软件在停止扫描余额之前允许出现的连续空地址队列长度。
当前,如果一个 coinjoin 回合完全失败了 —— 连归责阶段也无法产生一笔有效的交易 —— Wasabi 会在后续的 coinjoin 尝试中使用相同的输出地址。
那么攻击者可以从中知道什么呢?假设我们有一个回合失败了,其中有两个乃至更多(真正的)参与者。那么协调员和所有参与者,都在回合过程中知道了所有参与者集体想要的输入和输出。至于单个参与者想要的输入和输出(关联),则因为有多个参与者而受到 k-匿名集的保护。
再假设,该回合失败之后,一个或更多参与者加入了后续的一个 coinjoin 回合。除非是与上一回合完全相同的一组参与者尝试加入后续的这个回合,不然,地址复用就会打破 k-匿名集:本回合与上一失败回合的输入和输出出现了交集,就说明出现了同一位参与者,这就可以去匿名化这位参与者。
这一缺陷的修复措施就是在失败的回合后不复用地址。截至本文撰写之时,有一个公开的 PR,将标记用在失败回合事件中的地址。但尚不清楚,这种做法跟空地址限制会有怎样的相互作用。
也许可以使用一种基于 “ 静默支付” 的技术来解决这个问题。这样,用于一个 coinjoin 回合的新输出地址,就会由交易的输入(可能还需要 nLockTime 字段)来确定性地生成,从而,复原钱包一定是能够做到的,不论经过过多少失败的回合。这种做法的一个短板在于,Wasabi 确定性层级钱包的种子将跟其它所有钱包不兼容:你将 只能 在 Wasabi 钱包中找回资金。
最后,Wasabi 客户端支持通过一个 RRC 调用在 coinjoin 回合中直接发送支付。这样做能节约手续费(不必发送另一笔交易)。但这种特性天然容易出现我们这里说的问题:在经历过失败的 coinjoin 回合之后,这样的直接支付不换用新的地址、直接再次尝试。话又说回来,除了这是一个高级的、只能通过 RPC 来使用、不暴露给图形界面(GUI)的特性之外,GUI 也没有对 coinjoin 内直接支付的匿名性作任何说明。
3.3.1 泄露所有权同一的输入集合
避免了地址复用,并不能解决第二个(稍微小一些的)信息泄露,就是攻击者可以知道同一所有权人的钱币集合。出于效率,Wasabi 常常会在一个 coinjoin 回合中花费多个输入。因此,攻击者可以了解到不同钱币属于同一个所有权人的统计学证据。尚不清楚,在希望能够一次性花费多个钱币的 coinjoin 方案中,该如何完全缓解这个问题。
3.3.2 通过无效回合实现信息抽取
一种风险更大、但有可能获得更多信息的攻击,是这样的:协调员可以通过使用完全无效的输入,来假装有很多 Alice(实际上并没有这么多)。这是有风险的,因为在 Wasabi 协议中,参与者们在输出登记阶段以前就能知道该回合的所有输入 —— 为了实现最优的钱币面额挑选,这是必要的。能够访问最新 UTXO 集合的参与者就能侦测出这种欺诈。不过,当前的 Wasabi 客户端并不假设能访问 UTXO 集,因此,还不能自动检测出这种欺诈。
与通过失败回合来攻击相比,无效回合攻击的好处是一个行为不轨的协调员可以用更低的成本,获得关于意向输入和意向输出关系的更好统计信息。不过,一旦地址复用问题被修复,这种攻击也就没什么威力了,因为了解到的匹配关系基本上是无用的。
如前所述,虽然女巫攻击 coinjoin 回合总是有可能的,但是可以推断这样做会有高昂的成本,因为攻击者必须为成功的回合(所产生的被挖出的交易)支付手续费。
但要是你不必支付这一成本呢?
如果协调员可以诱使来自不同回合的不同的参与者签名同一笔有效交易,协调员就能重复使用其他参与者的流动性来女巫攻击每一个参与者。Wasabi 使用一个 256 比特的 “回合 ID” 来识别回合,它是通过 哈希参与该回合的所有价值 来生成的。重要的是,输入登记阶段的起始时间,以及协调员的身份。这两个信息就足以唯一地识别一个回合。此外,因为回合的所有设定(setting)都会哈希到这个回合 ID 中,如果保持了回合 ID 的一致性,协调员是无法通过行为上的差别来去匿名化不同的参与者的,因为不同回合有不同的设定。
在 coinjoin 期间,Wasabi 客户端会定期请求所有回合的状态。然后,在客户端决定参与某一个回合之后,它会在 与协调员互动的消息 中使用该回合的 ID 。在特定情况下,比如一个回合满员了,多个回合会并行发生;协调员可能会向不同的客户端广告不同的回合 ID 。
在输入登记阶段,所有的 Alice 都会发送自己的输入的 BIP-322 所有权证据给协调员。 这些所有权证据承诺了回合 ID,防止了所有权证据被重复用在其它回合中。最后,在签名前,协调员会给每一个客户端所有输入的所有权证据。在客户端收到这些所有权证据之后, 它们会得到验证。
Kogman 指出的问题是,只验证所有权证据自身是不够的:我们还需要验证这些所有权证据实际上与该证据意图证明的交易输入的脚本公钥(scriptPubKey)一一对应。Wasabi 客户端并不假设自己能访问有效的 UTXO 集合,因此不会直接验证所有权。
如果到此为止,那么所有权证据机制是可以被 “假冒” 的所有权证据愚弄的:真正(生成证据)的公钥并不对应于所有权证据意图证明的交易输入的脚本公钥。
但是,Kogman 没有考虑到 Taproot 签名 的工作原理:Taproot 输入的签名会承诺交易中所有输入的脚本公钥,意思是,任何假冒的所有权证据,最终都会产生一个无效的签名(无效的交易)。这种情形只是无效输入攻击的另一种形式(我们在上文 3.3.2 章节已经讨论过它了)。
此时,Wasabi 依然支持非 Taproot 的输入,因为历史上,许多服务都 很晚才采用 Bech32m(Taproot)地址。幸运的是,只要一个 Wasabi 回合中有 任何一个 非攻击者使用了 Taproot 输入,那么 所有 输入都必须具有有效的所有权证据。换句话说,为了通过攻击回合一致性来实现女巫攻击,恶意协调员必须拥有跟回合中的所有 Taproot 输入一样多的真实流动性(并花费同样比例的手续费),并且他们也只能攻击没有贡献 Taproot 输入的客户端。
为什么呢?因为诚实节点只会签名一个回合 ID 。假设一个回合中有三个 Alice 参与者:Adams、Brown 和 Turner 。我们假设 Turner 拥有一个以上的 Taproot 输入,而其他两人只有非 Taproot 输入。
如果这个回合要产生一笔有效的交易,协调员需要给 Adams 和 Brown 提供来自 Turner 的正确有效的所有权证据。然而,一旦协调员这样做了,TA 就只能给所有 Alice 参与者相同的回合 ID,从而击败任何女巫攻击的尝试,因为所有 Alice 参与者都将注册带有相同回合 ID 的输出;所有 Alice 的流动性都贡献给了整体上的匿名集。
请注意,这样的 Taproot 输入也可以是 你的 输入:给定你贡献了至少一个 Taproot 输入给 coinjoin 回合,你就可以确定,该回合中所有诚实的流动性都会贡献给同一个回合 ID 。现在,给 Bech32m(Taproot)地址的支付已经广受支持了,所以 Wasabi 默认生成 Taproot 存款地址会是一个好主意;截至 v2.6.0 版本,它还没有这样做。话说回来,输出地址有 50% 的概率是 Taproot 地址,这就保护了绝大部分 coinjoin,因为许多流动性都尝试登记至少一个 Taproot 地址。
此前,Kogman 在一个 Github issue 中提出过登记时延的问题。虽然 Kogman 并没有为这种批评提供一个清晰的工程基础,但我们可以:通信特征的 k-匿名集,在任何尝试以不同阶段身份分离来实现匿名的多方 coinjoin 方案中都是重要的。
回忆以下,Tor 提供了一种 TCP 流功能的匿名化等价物,通过固定长度的转发信元(relay cells)来路由。现在,想象你的互联网连接在同一个 coinjoin 回合的所有参与者中是 最慢的,慢得相等明显。换句话说,你得互联网连接速度并没有 k-匿名集。这是有可能的:协调员可以通过数据交互的具体时机来检测这种特征,然后通过观察输入注册和输出注册阶段的这种特征来去匿名化你的输入和输出。
如果 Wasabi 可以最终迁移到一种纯粹基于包裹的数据匿名性方案 —— 所有通信都是通过交换原子化的包裹来实现的,其时机特征可以完全随机化 —— 那就好了。不幸的是,在这样的方案中,得到了广泛利用且信任特性类似于 Tor 的,还不存在。也许,Wasabi 可以通过增加使用随机时延,在一定程度上优化现状。但没有完全基于包裹的通信方案,那么可能最好还是在一个相对常见的互联网连接类型中使用 Wasabi,这样可以最大化你的 k-匿名集。异曲同工,这一问题在参与者数量更多的回合中也能得到改善,因为 k-匿名集更大。
Kogman 也指出了这个问题的一个相关版本 1:在序列化和反序列化之间有细微差别。Wasabi 利用了 JSON 序列化,它是出了名的不明确,在不同实现中都有细微的差别。再说一次,你的 k-匿名集就是有多少参与者使用 完全 相同的序列化方案。细微的差别也可能导致协调员可以将你的输入和输出关联起来。
幸运的是,Wasabi 只有一种常用的实现,所以在现实中,这可能不会成为一个问题。但无论如何,Wasabi 最终应该转型承一个完全清楚的、严格的二进制序列化协议。
虽然 Wasabi 有许多方面可以提升,显然,它是目前参与 coinjoin 的最佳选择。支持 PayJoin 的钱包值得表扬,因为它能提供明显的好处 如果 支付者和收款方(的钱包软件)都支持它。不幸的是,尽管我希望能够推荐 JoinMarket ,丑陋的事实是,在区块链上留下关于钱币来自哪里的线索,是一个非常糟糕的错误,比任何理论上协调员可以付出高昂的代价、承担风险来背叛你的信任的问题都要更加严重。
你想想吧:你会更希望承担一个实体可能不值得信任、 并且 TA 可以找出一种方法来绕过 Wasabi 的密码学保护的风险吗?还是说,你情愿故意在区块链内将元数据广播给整个世界,使得现在和未来的 任何人 都能用它来去匿名化你呢?
虽然 受信任的 协调员是不受欢迎的;但 能够 信任你的协调员,也是一种双重保障。如果 Kruw 即使想要也不能去匿名化我的 coinjoin 交易,那当然是好事。但是, 在此之上,如果有一个人类层面的好理由,认为他不会这样做,也是好事。
JoinMarket 在第一个指标上就不满足:在通常的用法下,你的许多交易也可以因为手续费支付缺陷而被去匿名化。但它在第二种指标上也失败了:它完全基于经济和几率来挑选对手方,从而任何有闲钱的坏人都可以轻松成为你的对手方,然后将你去匿名化。这有点类似于如果 Tor 去中心化的话,也会变得 不那么 安全,因为没有任何使用人性元素来把坏人挡在外面的能力;没有任何办法证明你不会被记录日志。
Kogman 的夸张行为是告诉我们不要做什么的好例子。……(译者注:此段只涉及人物臧否,不译。)
任何时候,技术都不是完美的。我自己也不是只使用 Wasabi 。我喜欢使用 coinjoin 之后的钱币来开启闪电通道,并使用闪电网络来花费我的钱。这利用了两种非常不同的隐私性技术,从而,只有两者都失败了,我的隐私性才会受到影响。
2.Kogman 也批评了现已死去的 Samourai 钱包软件所用的 Whirlpool 协议。我们不会在这篇文章中讨论这个协议,因为 Samourai 钱包一直在有意变得非常不安全:它会默认泄露用户的 xpub(拓展公钥)。 ↩
3.Gregory Maxwell 的《 CoinJoin:适合真实世界的比特币隐私性》一文,再加上他更早的一篇《 I taint rich!》帖子,让这个概念流行起来。不过,甚至更早就有人提到了 coinjoin 的概念,例如,在 2011 年;Maxwell 也没有把自己当成发明人。至于 “coinjoin” 这个名字,是 Maxwell 私下请我给这个观念安一个好名字 —— 对于这个结果我非常高兴! ↩
5.比如说,我被私下告知,Sarah Meiklejohn 在 2013 年出版的《 A Fistful of Bitcoins: Characterizing Payments Among Men with No Name》聚类技术常常被区块链分析公司采用。然而,该文的方法纯粹是启发式分析,而不是合理的统计学概率分析,并且一开始也不是为这些目的而设计的。 ↩
6.这在显示中可能是真的,如果挂单人的收费策略差异很大,因为后续交易可能会因为收取不同的手续费而将他们去匿名化。但 JoinMarket 会在一定程度上将手续费随机化,通常能够缓解这个问题。 ↩
GingerWallet 也复刻了 Wasabi 钱包的源代码,当时 Wasabi 的中心协调员被关停了。因为 GingerWallet 似乎并没有得到很多开发,使用量也不大,所以我们不会再讨论。 ↩
5000, 6561, 8192, 10000, 13122, 16384, 19683, 20000, 32768, 39366, 50000, 59049, 65536, 100000, 118098, 131072, 177147, 200000, 262144, 354294, 500000, 524288, 531441, 1000000, 1048576, 1062882, 1594323, 2000000, 2097152, 3188646, 4194304, 4782969, 5000000, 8388608, 9565938, 10000000, 14348907, 16777216, 20000000, 28697814, 33554432, 43046721, 50000000, 67108864, 86093442, 100000000, 129140163, 134217728, 200000000, 258280326, 268435456, 387420489, 500000000, 536870912, 774840978, 1000000000, 1073741824, 1162261467, 2000000000, 2147483648, 2324522934, 3486784401, 4294967296, 5000000000, 6973568802, 8589934592, 10000000000, 10460353203, 17179869184, 20000000000, 20920706406, 31381059609, 34359738368, 50000000000, 62762119218, 68719476736, 94143178827, 100000000000 以及 137438953472 聪,这些数值是被 精心选择 的,以尽可能减少分解常见的数额所需要的平均 UTXO 数量。 ↩
9.一种 封闭 的 coinjoin 方案可以通过限制 coinjoin 参与者到一个已知实体的范围来防止女巫攻击。 ↩
10.关于 Wasabi 回合的统计数据已由 Wabisator 和 LiquiSabi 以及其它项目收集和发布。 ↩
11.这是最糟糕的情况。如果攻击者 并不知道 攻击目标希望参与 coinjoin 的所有钱币,攻击将是可见的,因为一些钱币将在输入登记阶段神秘地登记失败。 ↩
- 本文转载自: btcstudy.org/2026/01/14/... , 如有侵权请联系管理员删除。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!