
面向加密用户的大多数安全建议都聚焦于你看得见的表面:你的助记词、你点击的链接、你登录的网站。这些都很重要。但在这一切之下还潜伏着一种更安静的风险——软件本身,以及它由什么构建而成。一个钱包即便写得无懈可击,仍可能附带后门,因为现代应用由数百个第三方构件,以及一条把源代码变成你所安装二进制文件的构建流水线拼装而成。攻破这条链上的任何一环,你就攻破了下游的每一位用户。
这就是软件供应链,攻击者已经明白它是加密领域中杠杆最高的目标之一。本文解释供应链攻击究竟是什么、钱包为何是如此诱人的目标、在实践中真正站得住脚的防御,以及确定性构建能为你带来什么——包括 SSP 如何运用这一切。
什么是供应链攻击
供应链攻击并不直接侵入应用本身。它转而攻破应用所信任的东西:它引入的某个依赖、某位维护者的账户,或是拼装最终产物的构建流水线。恶意代码通过一次合法更新混入,经过签名并由正常渠道分发,因此看起来与你本想安装的软件一模一样。
这种间接性正是要害所在。攻击一个被广泛使用的库——或一台构建服务器——就能一次性触及成千上万的下游项目和数百万用户。对加密钱包而言,回报是直接的:在你钱包内运行的代码,已经能够触及最关键的时刻,即交易被签名、地址被显示之时。一个被篡改的依赖,无需通过钓鱼或薄弱的助记词卫生触及你,就能替换目标地址或窃取密钥材料。正因如此,这一类攻击值得在你的心智模型中占据一席之地。
两个近在咫尺的案例
两起真实事件展示了它如何上演——一个径直瞄准加密,一个则几乎击中整个互联网。
event-stream 与 Copay 钱包
2018 年,一个名为 event-stream 的热门 npm 包被移交给一位主动提出帮忙的新志愿维护者。这是一次例行的、看似出于善意的交接,正是开源中时刻发生的那种。随后,新维护者添加了一个新依赖 flatmap-stream,其中含有被混淆的恶意代码。
其载荷异常精准。它并非对所有人触发,而仅在一个特定的下游项目内激活:Copay 比特币钱包。在那里,它被设计来窃取该应用用户的助记词材料与资金。大多数引入 event-stream 的开发者从未受影响——代码确切知道自己要找哪个受害者。
这是一个经典的提醒:“我只装了一个小小的库”从来都不是全部真相。你也一并安装了那个库所信任的一切。
XZ Utils 后门
2024 年的 XZ Utils 事件(CVE-2024-3094)则更有耐心。XZ Utils 是一个压缩库,悄然存在于大多数 Linux 系统中。在数年时间里,一名攻击者以乐于助人的贡献者身份积累信任,逐步获得维护者职责,随后植入了一个旨在干扰 OpenSSH 的后门——OpenSSH 正是保护各地服务器远程登录的软件。
它几乎是被偶然抓住的,归功于一位察觉到几分之一秒延迟的工程师。倘若它被广泛分发,本可能把无数机器的远程访问拱手送人。
对加密而言,这一教训发人深省:该攻击利用的不是某个巧妙的漏洞,而是开源信任模型本身,靠一场长达数年的社会工程博弈,成为人人都依赖的那个人。
真正有效的防御
没有任何单一手段能拦住供应链攻击。奏效的是一整套手段的叠加,每一层都收窄攻击者的选择:
- 锁定依赖与锁文件。 锁定确切版本并将锁文件纳入版本管理,意味着一次构建无法悄悄拉取更新的、被篡改的发布。更新因此成为审慎、可审阅的事件,而非自动行为。
- 最小化依赖。 你添加的每一个包都是你所信任的一方。更少的依赖意味着更小的攻击面,以及更少可能被攻破的维护者。
- 依赖沙箱。 像 LavaMoat 这样的工具限制每个包在运行时能做什么,使被攻破的依赖无法自由触及网络或敏感 API。
- 代码签名。 经过签名的发布让用户能验证某个二进制文件确实来自真正的发布者,且在传输中未被改动。
- 第三方审计。 独立安全公司以对抗者的眼光审查代码与依赖,捕捉内部团队习以为常的问题。
- 可复现的确定性构建。 最强的结构性防御,也是值得细究的一项。
确定性构建详解
通常,从同一份源代码构建两次,可能产出两个略有差异的二进制文件——时间戳、文件排序与构建机器的细节都会渗入其中。这种变动性是个问题,因为它意味着你无法把良性差异与恶意差异区分开。
确定性(或称可复现)构建消除了这种变动性。在源代码相同的前提下,任何人、任何地方、任何机器,都会产出逐字节相同的产物。其含义是强大的:独立的人们可以从其公开源代码重新构建钱包,并确认你所下载的二进制文件与源代码所产出的逐位一致。若攻击者篡改了构建流水线或事后塞入了某些东西,哈希便不会吻合,篡改随即显现。
这翻转了信任模型。你不再需要听信发布者的一面之词;验证成为整个社区都能执行并相互核对的事情。Reproducible Builds 项目记录了这一实践在整个生态中的应用,而像 SLSA 这样的框架则定义了你可以据以要求一个项目的构建完整性保证等级。
SSP 如何运用这一点
SSP 将构建流水线视为其威胁模型的一部分,而非事后补丁。钱包以 Dockerfile 优先的确定性构建分发:由 Docker 定义的同一环境每次都产出相同的产物,因此一个已发布的版本可以从公开源代码重新构建,并与你所下载的逐位比对。SSP 还接受过 Halborn 的独立安全审查,其审计同时检视代码及其所依赖的依赖项。
还有一层是 SSP 构建方式所特有的,在此十分关键。SSP 是一个 2/2 多签钱包:每一笔交易都需要来自第二把密钥(即 SSP Key,位于另一台设备上)的独立批准。请精确看待它能做什么、不能做什么。确定性构建与审计降低了被篡改的构建一开始就被分发的概率;它们是第一道防线。但即便在最坏的情况下——某个构建不知怎地溜了过去——第二把密钥仍是一个独立的批准面,依然必须为每一笔交易签字放行。
它不是魔法盾牌,也不会让被攻破的构建变得可以接受。它只是意味着,一台设备上单个被篡改的组件,凭其自身无法动用你的资金。纵深防御才是要点。
你自己能检查什么
你不必是安全工程师,也能从这一切中受益。几个习惯就能走得很远:
- 只从官方来源下载。 从其官方网站或商店条目获取钱包,绝不从消息里的链接或搜索广告中获取。这与浏览器扩展卫生所讲的是同一种纪律。
- 优先选择公布确定性构建与审计的项目。 一个让社区得以验证其发布、并为独立审查付费的项目,正向你透露它的思考方式。
- 在提供签名与哈希时予以验证。 若某个发布附带签名或校验和,花上一分钟去核对。可复现构建只有在真有人去做比对时才能保护你。
- 保持整体 opsec 的严密。 供应链防御处于更宏大的图景之中;定期走一遍你的 opsec 清单,别让任何单独一层承担全部重量。
这些都不要求你信任单独某一方。这正是你想从自托管软件中获得的特性。
继续前行
一个钱包的可信程度,不会超过构建它的那条链。好消息是,这是少数拥有干净、结构性答案的安全问题之一:确定性构建加上独立审计,把“相信我们”变成“自己去验证”。
继续用钓鱼意识、助记词最佳实践、浏览器扩展卫生以及定期的 opsec 清单 来构筑你的防御。每一项都关上一扇门;合在一起,它们才是自托管安全真正的模样。


