惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

大猫的无限游戏
大猫的无限游戏
Webroot Blog
Webroot Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
T
Threat Research - Cisco Blogs
V2EX - 技术
V2EX - 技术
L
LINUX DO - 热门话题
Google DeepMind News
Google DeepMind News
Recorded Future
Recorded Future
S
Schneier on Security
I
InfoQ
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
The GitHub Blog
The GitHub Blog
S
Security @ Cisco Blogs
O
OpenAI News
W
WeLiveSecurity
Vercel News
Vercel News
阮一峰的网络日志
阮一峰的网络日志
Simon Willison's Weblog
Simon Willison's Weblog
人人都是产品经理
人人都是产品经理
Cloudbric
Cloudbric
The Last Watchdog
The Last Watchdog
The Hacker News
The Hacker News
Google Online Security Blog
Google Online Security Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
GbyAI
GbyAI
NISL@THU
NISL@THU
T
Tailwind CSS Blog
V
Visual Studio Blog
PCI Perspectives
PCI Perspectives
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Jina AI
Jina AI
D
DataBreaches.Net
B
Blog RSS Feed
N
News and Events Feed by Topic
N
News and Events Feed by Topic
H
Heimdal Security Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
腾讯CDC
Latest news
Latest news
V
Vulnerabilities – Threatpost
Hacker News: Ask HN
Hacker News: Ask HN
WordPress大学
WordPress大学
V
V2EX
aimingoo的专栏
aimingoo的专栏
博客园 - 司徒正美
Apple Machine Learning Research
Apple Machine Learning Research
D
Darknet – Hacking Tools, Hacker News & Cyber Security
The Register - Security
The Register - Security
Help Net Security
Help Net Security

smallyu的博客

为什么买的加密货币一定要去中心化 RISC-V 虚拟机无法代替 EVM 虚拟机 Polkadot 的 Existential Deposit 机制错在哪里 利息,套利,交易策略,金融市场 LayerZero 从来不挑战比特币的地位 默认参数引起的以太坊节点运行错误 硬件钱包与资产安全 预测市场比币圈更赌场 为什么去中心化的跨链桥不可能实现 我对于 AI 时代的答案 不要投资任何隐私币 区块链技术世界的三大真理 以太坊 AA 钱包的致命问题是什么 基于 AI 语义执行的 MCP 区块链的设计 一个集成 Geth 和 CometBFT 的兼容层 我的加密货币定投策略(二) DeFi 基础: 理解 AMM 定价机制 Go 语言 GMP 调度器的原理是什么 Web3 项目分析计划 对 Psyche Network 项目的分析 continuation 教程: 理解 CPS 如何开发一个比特币符文(Runes)协议 比特币脚本开发教程 我从王垠的计算机科学视频班学到了什么 区块链技术面试题(2025年版) Rust 语言容易让新手困惑的一个“过度优化” Solana 智能合约开发教程 (1) 尝试开发一个最小 EVM 虚拟机 基于 ZK 的链上身份系统设计 一个 Web3 打赏系统的设计 鼓吹 Cursor 的人技术能力都差 关于 Code Review 的礼节 假如启动一个新的以太坊 PoS 网络 发行加密货币的最好方式 所有 BFT 共识的区块链都是中心化的 对 2025 年区块链行业的预测 Restaking 项目的经济难题 如何看懂任意区块链项目的技术架构 为什么不要做以太坊的二次开发 为什么不要做智能合约开发和 DeFi 开发 我的加密货币定投策略(一) PoS 类型的区块链如何处理分叉 Ethereum Casper 为什么需要 EIP-7251 区块链中的 PBFT 不需要第二次投票 开发者的思维方式 发币的核心要点 炒币投资的小 tips 为什么说 PoW 比 PoS 更加去中心化 牛市对普通人来说意味着什么 如何健康地远程工作 为什么比特币不用概率加密函数 程序员的 “服从权威” 心理 区块链技术面试题 如何区分公有链和联盟链 对 Layer 2 项目创业想法的回复 对区块链共识机制的理解 Pebbling Game 鹅卵石游戏 PDP 文件证明的局限性 不要小瞧 ChatGPT 为什么炒币不是一个好主意 一种在区块链上生成随机数的机制 为什么以太坊的私钥计算不可逆 “猜均值的2/3” dApp 游戏设计 Proof of Storage/Space/Replication 的区别 Proofs of Retrievability 文件证明的含义 对 S-PDP 文件证明的示例和解释 我的加密货币交易机器人 对区块链行业的见闻 随机确认块的共识机制 VRF + BFT 共识引起交易失败的问题 为什么要重视编程思想 对 Web 3.0 的理解 GitBook 好用吗? 一种区块链节点存储扩容的方式 一种基于“自我中心主义”的共识机制 链表常见算法题及解析 基于 Multi-Linked List 的区块链设想 理解哈希函数与序列化 联盟链比公有链差在哪儿 在 Dijkstra 算法中保存路径 为什么数字货币使用区块链是政治问题 区块链:下一代数字身份认证体系的基石 网页技术能实现 3D 建模吗? 给区块链一个定义 从 Erlang 开始了解 Actor 模型 一种侧边导航栏的交互方式 Rust 的 ownership 是什么? Haskell 中的 Monad 是什么? 浅析 Libra 背后的区块链技术 对区块链的理性认识 Rust 基础语法概述 基于 Java 的爬虫框架 WebCollector Kotlin:简化版的 Scala JavaScript 有关联数组吗? 主流编程语言的异常处理机制 Go 语言基本语法 Scala 语法基础 用 Scala 改写 Java 浅度实践 Python 获取海贼王更新信息 HTML5 音乐可视化
关于以太坊的私钥碰撞
2023-01-18 · via smallyu的博客

关于以太坊的私钥碰撞

2023-01-18

如果你有 1/100000000 的机会暴富,你愿意尝试一下吗?

以太坊私钥

以太坊的账户完全由私钥控制,根据私钥可以推算出账户的地址。私钥是一个 64 位长度的 16 进制字符串,比如:

0xd110227375ab838e8743192d278c105e30f253c966987c50b754412c9b986fe3

你可以在任何支持以太坊账户的钱包,用这个私钥导入对应的账户。这个私钥对应的账户地址是:

0x00000006A3D4DA3A559829B1730603CAeE97cC3D

你也可以根据这个账户地址,在以太坊浏览器上查询到账户相关的交易记录等信息。

私钥碰撞

既然私钥只是一个字符串,那么有没有可能,随机生成一个字符转,这个私钥对应的账户地址,正好有钱?因为有了私钥就能够控制账户上的所有资产。以太坊上有钱的账户那么多,有的余额还特别高,万一正好生成了一个私钥,那岂不是直接暴富。

当然随机生成的字符串,必须是 64 位长度 16 进制。为了避免以太坊的 SDK 存在某些防碰撞的规则,我们可以直接粗暴一点生成,比如这样:

let s = "0123456789abcdef";
let hex = "0x";
for (let i = 0; i < 64; i++) {
  hex += s[Math.floor(Math.random() * 16)];
}

这样做足够直观,在字符串层面随机拼接出 64 位长度的。LeetCode 的简单题就是天天搞这种。虽然实际上以太坊并没有防碰撞的机制。

碰撞概率

我们来计算一下,随机生成私钥,碰撞到有效账户的概率。假如存在一个地址,我们想要正要随机生成这个地址的私钥,可能性是多大?

16 进制就代表每一位字符,和目标私钥一致的可能性是 1/16,一共 64 位长度,概率就是 (1/16)64

p = (1/16)^64
  = 1 / 16^64
  = 1 / 115792089237316195423570985008687907853269984665640564039457584007913129639936

把零头抹掉,只计算数量级的话:

p = 1 / 115792089237316195423570985008687907853269984665640564039457584007913129639936
  = 1 / 100000000000000000000000000000000000000000000000000000000000000000000000000000
  = 1 / 10^77

这是一个非常低的概率,中国中奖率最低的大乐透彩票,中奖概率是千万分之一,也就是 1/10^8。以太坊的私钥碰撞,想正好是某一个账户的可能性,相当于连续中 10 次彩票。这是几乎不可能发生的事情。

不过彩票的中奖是有速度限制的,比如需要 1 天才开奖。加密货币领域的私钥可不是,如果提高随机生成私钥的速度,能不能增加碰撞成功的概率呢?

目前比特币全网的哈希率是 270M TH/s。比特币挖矿的过程本身就是不断地做哈希计算,直到找到拥有 n 和前导 0 哈希值的字符串,所以比特币的哈希率也可以用来描述私钥的生成速率。做一下单位换算

r = 270M TH/s
  = 270000000 TH/s
  = 270000000000 GH/s
  = 270000000000000 MH/s
  = 270000000000000000 kH/s
  = 270000000000000000000 /s
  = 100000000000000000000 /s
  = 10^20

这个结果只保留了数量级。假如你拥有全球比特币矿机的算力,去做以太坊的私钥碰撞,每秒钟的概率是:

ps = p * r
   = 1 / 10^57
   = 1 / 1000000000000000000000000000000000000000000000000000000000

这仍然是一个低到遥不可及的可能性。如果碰撞持续尝试 1 年呢?

py = ps * 60 * 60 * 24 * 365
   = ps * 31536000
   = ps * 10000000
   = ps * 10^7
   = 1 / 10^50
   = 1 / 100000000000000000000000000000000000000000000000000

持续运行 1 亿年呢?

pb = py * 100000000
   = py * 10^8
   = 1 / 10^42
   = 1 / 1000000000000000000000000000000000000000000

可以看到,时间对于概率的增加幅度,是微乎其微的。计算能力也许有可能成倍增长,比如苹果 M 系列芯片,比 Intel 芯片高几倍速度的提升。但是在 70 个 0 的数量级面前,这样的提升仍然微不足道。

即使拥有 1 亿个地球的比特币算力,运行 1 亿年,也只是能再减少几个 1 后面的 0,远远达不到碰撞成功的目的。

尝试一下

虽然可能性非常小,但我还是想尝试一下。

我写了一个脚本 eth-collision/eth-collision-random,随机生成私钥后,根据私钥的账户地址,自动去 etherscan.io 上查询账户余额,如果余额大于 0 会把私钥输出到日志文件里。由于 Etherscan 对 API 的调用次数有限制,脚本会以每秒 20 个地址的速度去查询,也就是一天能尝试 172 万个地址。

这个速度不够快,有更好的办法吗?凡是第三方服务,大多数会有 API 速率的限制,想不受限制进行查询,只能自己运行一个以太坊节点了。以太坊节点最低的硬件要求,是 4 核 16G 内存 1T 硬盘。这样配置的服务器,在 Vultr 上的价格至少要 300 美元一个月。有点贵。而且运行起节点后,还需要自己写一写程序,根据每个块的交易信息统计出有余额的地址。整个周期会很长。

我注意到 这个页面 提供了以太坊上余额最多的地址列表,1 页 100 个,总共 100 页。我写了一个爬虫 eth-collision/eth-address-top-list 到这个页面上抓取数据,这样就能得到以太坊余额最多的 10000 个账户地址的列表。

根据抓到的 10000 个地址,程序就可以比较快地运行了,而不需要受到 API 速率的限制,也不需要自己跑全节点。由于不看好 JavaScript 的运行速度,我用 Golang 写了一个程序 eth-collision/eth-collision-match-address,启动 100 个协程来加快生成私钥的速度。程序会把 10000 个地址读到一个 map 里,然后判断随机生成的账户是否在目标列表内。JavaScript 的一个 for 循环也足够把 CPU 跑满,但是直觉上总感觉 Golang 会更快一点。

对了,Golang 中的 map 记得加互斥锁。因为 map 不是并发安全的。不过加锁会降低速率。为了解决需要加锁的问题,因为只有 10000 个地址,占不了多少内存,所以可以实例化多个 map,有多少个协程就有多少个 map,每个协程在自己的 map 上做验证。这样就能充分保证私钥的生成和验证效率。

10000 个地址是不是太少了?以太坊一共有那么多个地址。一共有多少个呢?从 Etherscan 统计目前有 230M 左右,大概 2 亿多个。

后来我发现了一个仓库 eth-collision/Wallet-private-key-collision-brute-force-tool,这个仓库里提供了一个 OneDrive 文件的下载链接,是一个包含 1.8 亿条账户地址的文件,这些账户都在链上有过交易记录。文件的压缩包有 4.4G 大,解压后 16G 左右,是 pkl 格式的文件,然后我用 Python 解析成了 txt 文件。

在得倒这么多账户地址的列表后,现在的问题就变成了,该怎么利用这些数据。

首先是像原先一样,把所有数据读到 map 里。这么多的数据读到内存里,占用的内存可能至少 16G,也就是需要 24G 内存的服务器。Vultr 上最便宜的符合要求的服务器,接近 150 美元一个月。况且那么大数据量,Golang 的查询效率也是个疑问,还得加锁,限制比较多。

有没有好的方案?用数据库的话,MySQL 是支撑不住亿级别的数据查询的,记得之前参与的一个项目,在上亿数据里做最简单的查询要 10 秒以上,还是单次查询。现在的需求是每秒钟查询上千次。Redis 呢?Redis 的查询效率应该是有保证的,可 Redis 还是会把所有数据读到内存里。在 Redis 的介绍里,1M 个 key 需要 85M 的内存,换算一下:

1M   -> 85M
180M -> 180 * 85M
     = 15300M
     = 15G

Vultr 上,16G 的 Redis 价格很高,比服务器贵多了,需要 480 美元一个月。至于更沉重一点的数据库,像 Elasticsearch 或者更专业一点的 HBase 之类,从数据库搭建到导入数据,然后处理数据,一整套下来确实麻烦了一点。服务器开销也不见得更低。

再后来,看到有个东西叫布隆过滤器,正好符合这样的使用场景。我试了一下,容量 2 亿条数据的布隆过滤器,容错率 10 亿分之一,在加载完 1.8 亿条数据后,导出的二进制文件,只占用 1G 的磁盘空间。加载到内存中,也只需要占用 1G。

这样的方案其实挺好了。我在服务器上运行碰撞程序,每个月需要 30 美元的 2核 4G 服务器,每个小时可以尝试 60M 个地址。每个月需要 600 人民币的 8核 16G 服务器,每个小时可以尝试 160M 个地址。

当然,用再好的服务器都没有用,用整个地球上的算力都没用。

靓号地址

以太坊的账号地址也有靓号一说,比如地址 0x00000006A3D4DA3A559829B1730603CAeE97cC3D 包含有 6 个前导 0。关于靓号地址可以参考这篇文章

我写了这个程序 eth-collision/eth-collision-find-address 来寻找靓号地址,一般来说,找到 6 个前导 0 的地址是非常容易的事情,在 Macbook Air M1 上几分钟就可以。包含 7 个前导 0,可能需要半个小时。包含 8 个前导 0,就需要一两天。

包含有 10 个前导 0 的地址,已经算是非常非常稀有了。不过当然靓号地址没什么用,你一旦知道私钥,这个账号就是你的了,给别人别人也不要。

在线手动碰撞

这是一个在线手动进行私钥碰撞的网页,可以根据私钥计算出公钥,也可以生成随机的公私钥对,并且点击链接能够直接跳转到 Etherscan 检查地址对应的余额。

地址:http://eag.smallyu.net

源码:smallyunet/eth-address-generator

页面是纯前端实现的,可以离线使用,不会有任何安全问题。