Coldcard 黑客事件解析:RNG 缺陷、受影响固件与迁移方案

阅读时长 5 分钟

Coldcard 黑客事件解析:RNG 缺陷、受影响固件与迁移方案

首页>Industry Insights>Coldcard 黑客事件解析:RNG 缺陷、受影响固件与迁移方案
分享

没有人动过任何设备。

没有钓鱼邮件。没有恶意应用。没有被盗的笔记本电脑,没有泄露的备份,没有输入到假冒支持页面的助记词。7 月 31 日在 Coldcard 黑客事件中损失比特币的人,按照标准建议做对了每一件事:私钥离线生成、使用专用硬件、使用一台完全建立在“不信任任何其他东西”这一声誉之上的设备。

在 01:31 至 01:56 UTC 之间,CoinDesk 测得第一波扫荡:594 BTC 在三个区块的时间窗口内、通过 1,324 笔交易、从约 500 个钱包中被转走。总共二十五分钟。随后几天又出现了更多轮扫荡。

其中有一点会改变你接下来的做法:攻击者从来不需要访问任何人的 Coldcard。他们是从零推导出助记词的。

Coldcard 黑客事件中真正被攻破的是什么

先从助记词是什么说起,因为整个故事都建立在这一个事实之上。

你的 12 个或 24 个单词并不是密码。它们是一个非常大的数字,以人类抄写时不易出错的格式写下。保护你的正是这个数字。而这个数字之所以安全,唯一的原因是它从一个大得没有人能搜索的池子中以不可预测的方式被选出。

这个池子用比特来衡量。每增加一个比特,池子就扩大一倍。一个正确生成的种子携带 128 比特的不可预测性,约合 340 undecillion(3 后面跟 38 位数字)种可能。任何现有的机器、或任何工程路线图上的机器,都无法穷举这么大的池子。这就是自托管之所以安全的全部基础。

因此,硬件钱包最重要的工作发生在它生命的最初几秒、在你签署任何东西之前:它必须生成一个真正不可预测的数字。Coldcard 为此配备了专用硬件——一个从物理噪声中取样的真随机数生成器。

而在受影响的固件上,五年时间里,这个硬件从未被调用过。

一个编译标志如何把硬件钱包变成可预测的钱包

起因小到一句话就能说完,而这正是它值得理解的原因。

Coldcard 的代码定义了一个名为 MICROPY_HW_ENABLE_RNG 的设置并将其设为零,因为他们使用的是自己的硬件生成器,而不是 MicroPython 内置的那个。一个在 2021 年迁移期间引入的配套加密库,检查的是该设置是否存在,而不是它是否被开启。它存在,值为零。检查通过了,本应阻止构建的安全错误从未触发,代码便悄悄落到了 MicroPython 的软件回退路径上。

Coinkite 自己的话说:"The guard used #ifndef, which tests whether MICROPY_HW_ENABLE_RNG is defined, rather than whether its value is nonzero. We defined that macro as zero, so the #error did not stop the build."(该防护使用了 #ifndef,它检测的是 MICROPY_HW_ENABLE_RNG 是否被定义,而非其值是否非零。我们将该宏定义为零,因此 #error 没有阻止构建。)

这个软件回退并不随机。Block 的分析显示,它由芯片的硬件 ID 加上一个定时器值启动,再由实时时钟寄存器补充,而这些值只读取一次、从不刷新。Coinkite 对此的描述是种子“主要来自设备与计时状态”。这些没有一样是秘密。给这样的生成器输入相同的起始值,它每次都会可靠地、按设计地产出相同的输出。

于是池子缩小了。在 Mk2 和 Mk3 设备上,它塌缩到大约 40 比特,约合 1.1 万亿种可能。一万亿听起来很大,其实不然:一台不错的笔记本电脑就能穷举完,一个 GPU 集群几个小时就能搞定。

Mk4、Mk5 和 Q 会混入来自安全元件的额外熵,而已公开的两份分析正是在这里出现分歧。Coinkite 估计这些型号的有效搜索空间约为 72 比特。Block 发现重新播种只从安全元件取四个字节,仅替换生成器内部状态的一个字、其余原封不动,按其估算“最多留下 2^32 条可安全区分的输出流”。Block 谨慎地表示尚未完成完整的实证测试来确认可利用性,并建议读者等待 Coinkite 的最终报告。

请把这一分歧当作仍在进行中的争论。如果你持有 Mk4、Mk5 或 Q,更稳妥的做法是采用较悲观的假设。

接下来的攻击就是机械性的了。生成候选种子,推导每个种子会产生的比特币地址,把这些地址与公开区块链比对,然后扫走有余额的地址。区块链是公开的,因此这一切不需要碰任何钱包、任何网络连接或任何人。

屏幕上没有任何东西能提醒你

这个细节值得你记住得比固件版本号更久。

一个弱的随机数生成器产出的结果看起来并不弱。设置过程中 Coldcard 屏幕上显示的单词看起来和正确生成的种子一模一样,因为它们格式正确、校验和正确、统计上毫无异常。可预测生成器的输出可以轻松通过随机性测试。它看起来是随机的,只是它的结果早已被一个任何人都能重建的起始值决定。

你再小心也发现不了这个问题。检查备份、验证地址、先试一小笔交易——这些都发现不了。所有这些检查都会通过。

该漏洞由 Block 的比特币工程与安全团队发现,他们通过固件分析追踪到它,并在公开发布前向 Coinkite 披露。它自 2021 年 3 月的固件 4.0.1 起就一直随产品发布。

Coldcard 黑客事件究竟影响哪些人

这比标题数字更重要,因为该漏洞只会波及在受影响固件上生成的种子。根据 Coinkite 的公告

受影响,请迁移种子:

  • Mk2 和 Mk3,固件 4.0.1 至 4.1.9。约 40 比特。请视为紧急。
  • Mk4 和 Mk5,低于 5.6.0。约 72 比特。
  • Q,低于 1.5.0Q。约 72 比特。

不受此漏洞影响:

  • TAPSIGNER、OPENDIME 和 SATSCARD,它们运行不同的代码库。
  • Mk1。Coinkite 的公告没有列出它的归属,但 Block 的分析发现 Mk1 至 v3.2.2 直接使用 STM32 硬件生成器,该回归直到 v4.0.0 才引入。
  • 使用至少 50 次公平、独立、私密掷骰生成的种子。Coinkite 表示这些“仅就这一 RNG 问题而言”没有风险,并要求你在迁移前阅读其单独的指引,而不是想当然地认为自己没事。

在另一台设备上生成并导入 Coldcard 的种子应当也不在此列,因为该漏洞位于生成环节而非存储或签名环节。Coinkite 的公告并未直接谈及导入的种子,所以这是机制推断而非官方的安全确认。

更新固件无法修复已经存在的种子。那个弱数字多年前就已一次性生成,而它现在仍然是保护你币的数字。补丁阻止的是新种子被错误生成,它无法追溯。

持有 Coldcard 该怎么做

Coinkite 的指引,按顺序:

  1. 先从官方来源更新到修复后的固件,然后再生成任何新内容。Mk2 和 Mk3:4.2.0 或更高版本。Mk4 和 Mk5 Standard:5.6.0 或更高版本。Q Standard:1.5.0Q 或更高版本。Edge 版本:6.6.0X,Q 为 6.6.0QX。
  2. 在更新后的设备上生成一个全新的种子。在 Mk4、Mk5 和 Q 上,修复后固件自身的种子生成已足够,掷骰可选。
  3. 记录并核验新的备份、钱包指纹和一个收款地址。如果你设置了口令(passphrase),请与助记词分开存放。
  4. 在转移剩余资金之前,先发送一笔小额测试交易。
  5. 保留旧备份,直到迁移完成并确认。

最后这一步值得读两遍。发生此类事件后的本能是立刻销毁旧备份,而如果在迁移中途出任何差错,这种本能会让你损失资金。旧种子已泄露,但在资金确认进入新钱包之前,它仍是唯一能触及资金的东西。事后再退役它,而不是在过程中。

如果你的 Mk3 上的种子是 2021 年以来任何时候生成的,请在今天、而不是这个周末完成第一和第二步。四十比特真的很低。

关于你见过的那些报道数字,说一句。Galaxy Research 统计到,截至 8 月 4 日,约 7,300 个地址共被取走 1,596 BTC。TRM Labs 公布的数字约为 1,816 BTC(约合 1.16 亿美元),涉及超过 5,200 个地址。两家机构都称数字为初步统计,各自撰写时资金仍在流动,而 Coinkite 尚未公布自己的损失估计。预计总额还会继续变化。上述固件指引没有争议。

自托管中没有人能检查的部分

大多数面向持有者的安全建议针对的是你能观察到的东西。发送前核对地址。验证域名。不要把助记词输入任何东西。从制造商处购买,而不是从第三方市场购买。这些都是好建议,而它们全都关于在错误发生时当场抓住它。

密钥生成不同。它只发生一次,不产生任何关于自身质量的证据,而当它出错时,系统里没有任何信号告诉你。你的钱包正常工作。你的交易正常确认。你的备份能正确恢复。这个失败完全无声,直到它不再无声。

这才是这里真正的教训,而且它远远超出一家制造商的范围。任何钱包,无论硬件还是软件,都在就随机性做一个你自己无法审计的承诺。你信任的是一个你永远看不到的构建过程。

这指向了当这种信任被错付时真正能减少损失的东西:一个单独的秘密本身值多少钱。

在这次事件中损失比特币的每一个人,都是在同一笔交易中失去全部。不是因为攻击者多高明,而是因为一个数字就是整个安全模型。猜中数字,就拥有钱包。没有第二道关卡需要越过。

当没有任何单一秘密等于整个钱包时,什么改变了

CoinWallet 支持多方安全计算(MPC)。不是一个助记词承载一切,而是把签名能力拆成由不同地方持有的多个分片,必须有一定数量的分片凑齐,交易才能被批准。

任何单一分片都无法动用你的加密资产。只有所需数量的分片协同工作,才能批准任何交易。一把私钥、一台设备、一个被盗的分片,永远不够。

在实践中,这意味着你可以创建 MPC 钱包并与他人共同管理资产、通过邀请码加入钱包、导入已有的密钥分片,并通过阈值门控流程更换丢失的设备,而不是依靠一条能解锁一切的单一恢复短语。

现在是诚实的部分,因为这个事件值得诚实:MPC 并没有取消随机性要求。密钥分片也要生成,生成质量依然重要。拆分做到的,是消除那个可被猜出的单一秘密。推导出一个分片的攻击者只拥有一个分片,而一个分片签不了名。失败必须发生在不止一处你才会有损失,而要安排这一点,比一个弱数字困难得多。

比特币上的多重签名通过另一条路径给你类似的性质:几把独立密钥、要求一定数量的签名,没有一条交出一切的短语。

建议其实没有变,只是向前挪了一步。多年来给持有者的信息是把你的密钥从交易所移到自己的硬件上,那个信息是对的。这次事件补上了下一句:把密钥放到自己的硬件上值得做,但这不等于安全,因为你只是把信任从一家可能被黑的公司,转移到了一个五年来厂商之外无人读过的构建过程上。

CoinsDo Team

作者

CoinsDo Team

business@coinsdo.com