我所经历过的私钥生成投毒攻击事件

本文作者:小鱼·币币机 | Croath@cr0ath。发文时间:上午9:15 · 2025年10月17日


2018 年我主导了一个社区开源项目,是 EOS SDK 的 Swift 实现(大家不要用,已经 6 年没有维护过了),使用的苹果自带的密码学框架提高安全等级。

刚开始写的时候犯懒了,随机生成私钥没有使用密码学框架,而是手写了一个随机算法,写着写着又懒了,就想去网上搜索一段随机算法。结果一搜,stackoverflow 上正好有一段随机算法,而且是特别为私钥设计的,我直接复制来用,果然好用,签名转帐什么的功能都没有问题。

我所经历过的私钥生成投毒攻击事件 后来开始补单元测试,就发现了问题。我想生成一批私钥公钥对,放到单元测试中,以防未来的修改对私钥生成造成影响,因为能确认目前的生成算法是正确的,就用自己写的代码生成批量私钥,但是生成出来的私钥放在一起看总觉得怪怪的,就打印出了原始 byte 数组,发现里面有好多好多连续重复的 0。这是非常不应该的,理论上所有数字出现的概率是一样的,不会有大量的 0 出现,立刻着手排查原因。

很快就确定到是那段复制来的随机算法出了问题,知道问题出在那段代码,但是却看不出问题在哪,怎么看都觉得是正确的。

排查代码花了很久时间。因为看不出问题所在,开始一行一行检查,还是看不出。怕自己粗心,开始一个字符一个字符检查,终于发现了奇怪的地方。那串随机字符串来源生成的模板字符串 “0123456789abcdefgh…zABCDEF…Z” 里(我不记得具体的了,只是举例是这样的字符串),有两个字母中间,按一次向右方向键,不会跳到下一个字母后面,而是按好多次才会跳过去,开始还以为键盘坏了。用鼠标点到下一个字母后面,按向左方向键,也要按好多次才会按到前一个字母那里,光标就好像卡在了两个字母中间一样。

说到这里很多有经验的朋友已经猜到了,是零宽连字 Zero Width Joiner(U+200D)。Unicode 里有很多零宽的字符,比如零宽连字、零宽不连字、零宽空格,我统计到的就有十几种。他们在普通的编辑器里是「零宽度」的,也就是肉眼看不见的,在特殊场景有用途。

比如说在下面这张图的 abcd 中间,你能发现还有一个看不到的字符存在吗?我所经历过的私钥生成投毒攻击事件

这里零宽字符就用在了私钥生成算法的投毒攻击上,因为在随机算法的最后有一个恶意校验代码,所有其他字符都被换成了 0,而原本的字符来源被插入了几百个零宽字符,这也就导致出现 0 的概率大大增加了(大概 90% 都是 0),私钥失去了真随机性。

还好我在代码开源之前就发现了这个问题并且修掉了,但是不知道那条 stackoverflow 上的投毒答案已经被多少人复制使用过了。

——

这个事件是我本人经历的。

其实当时也发生过另一起很大的事件,国内 top3 的交易所之一,推出了自己的钱包 app,刚推出就频繁有人开始被盗。我从小道消息得知,不知道是程序员故意的还是过失,生成的私钥不是从随机字符串随机来的,而是通过 unix 时间戳转换来的。这样的方式非常巧妙,私钥本身看不出什么奇怪,但是如果你把某段时间的所有毫秒级 unix 时间全都生成一遍,你就拿到了所有用户可能使用过的私钥,从里面找有钱的就可以盗取资产了。后来没过几天该钱包 app 升级了,问题被修复,被盗的人也都被归因为私钥保存不善,但是有多少人至今还在使用当时有问题的私钥就不得而知了。

Cos(余弦)😶‍🌫️@evilcos:慢雾Slowmist 创始人

还有投毒 AI 的,别信 AI 给出的代码,尤其是做敏感处理的,一定要用成熟知名的开源代码(但又要注意没被供应链投毒,好累…)。还有一种思路就是多对比知名钱包(包括硬件钱包)的开源实现,多看多对比,嫌麻烦就用顶流知名度的钱包吧…出事了,整整齐齐…

然后我们会紧盯着,有风险会及时告知

© 版权声明

相关文章

暂无评论

暂无评论...