← 返回子刊列表

随机数不随机,比特币就不安全:12万枚比特币被盗背后的隐秘漏洞

作者:lixiang90, ChatGPT

发布时间:10/17/2025, 6:16:59 AM

查看使用的 Prompt

写一篇文章,讲解不安全的随机数生成器给比特币用户带来的风险,提醒用户和开发者安全实践的重要性。 美国执法机构近期查获超过12万枚比特币,据披露,执法机构并非通过破解或入侵方式获得私钥,而是因发现这些私钥在生成时存在随机性缺陷。据不完全统计显示,受该漏洞影响的地址超过 22 万个,完整列表已公开。这些钱包的私钥由有缺陷的伪随机数生成器(PRNG)产生。由于PRNG使用了固定的偏移量(offset)和模式,导致私钥的可预测性增加。 警惕客户端漏洞,可能会有一些比特币钱包的程序员缺乏经验,使用不安全的随机数生成算法生成私钥,这样就会有安全问题。 举例:常见的随机数函数,例如python的random就是不安全的,不能在要求密码学安全的领域使用 import random private_key = hex(random.getrandbits(256)) # 危险!会导致私钥可推算漏洞 python默认的random算法是使用线性同余生成器(Linear congruential generator,LCG),实际上是使用同余方程 计算的伪随机数。在了解部分值或参数等信息的情况下,它是很容易被推算的。 正确的做法是使用密码学库,例如Python 的cryptography库提供的安全随机数生成器。

导语:

比特币世界里,最危险的往往不是黑客入侵,而是开发者的一行代码。美国执法机构近期查获超12万枚比特币,并非通过破解获得私钥,而是因这些钱包在生成时使用了“伪随机”的随机数。随机性缺陷让原本牢不可破的加密系统变得脆弱,22万个地址因此暴露。本文将带你了解,不安全的随机数生成器如何让比特币用户资产瞬间归零,以及开发者应如何避免重蹈覆辙。

前言:为何“随机性”在加密世界如此关键

在比特币(或其它基于椭圆曲线加密的系统)中,安全的核心是 私钥(private key)。这个私钥是一个在 [1, n–1] 范围内的随机整数(n 是椭圆曲线的阶数,如 secp256k1 的阶)。一旦这个私钥被泄露或可被猜出,攻击者即可完全控制对应公钥地址上的资产。

因此,私钥的随机性非常关键。它必须不可预测、足够熵(entropy)且不受外界已知因素影响。否则,即使加密算法本身(曲线、签名算法等)再安全,也可能因为“随机性破坏”而被攻破。

在最近美国执法部门查获 12 万枚比特币的案例中,据报道,这些比特币私钥并非因破解或暴力攻击获得,而是因为其生成过程中使用了有缺陷的伪随机数生成器(PRNG),导致这些私钥可被预测或恢复。从这一事件中,我们可以看到:随机性缺陷可以导致灾难性后果

下面我们从技术层面解析这种风险、历史案例、攻击方式,以及对用户和开发者的建议。


有缺陷的随机数生成器:风险来源与攻击策略

什么是伪随机数生成器 (PRNG) 与加密安全 PRNG (CSPRNG)

  • PRNG(伪随机数生成器):通常是一个确定性算法,根据内部状态(种子、状态变量等)产生看起来像随机数的输出。非加密用途的 PRNG(如游戏中的随机、数学模拟中的随机)不需要抗攻击性,只要看起来“够随机”即可。
  • CSPRNG(加密安全的伪随机数生成器):这是专门为加密用途设计的伪随机函数。它应满足“不论部分状态被泄露,也难以推算之前/之后输出”的性质(即 next-bit 安全性、状态恢复困难性等)(维基百科)。

用在关键领域(如私钥生成、签名中的随机 nonce)时必须使用 CSPRNG,否则可能引入致命漏洞。

如果使用了不安全 PRNG,会有什么问题

当私钥或签名过程用到的随机数可预测或部分已知时,攻击者可能:

  1. 直接预测或穷尽种子/状态 若 PRNG 的状态空间较小(例如只有 32 位、或使用简单的线性同余 / 线性反馈移位寄存器等),攻击者可以通过枚举所有可能的状态,恢复整个随机数输出流,从而推算出私钥(或 nonce)产生过程。

  2. 从部分已知输出恢复状态 在某些设计不良的 PRNG 中,若攻击者知道部分输出(例如在签名过程中泄露的随机 nonce 或签名字节),就能反演出内部状态或下一次输出,从而恢复新的私钥或伪造签名。

  3. 重放 / 碰撞攻击 如果多个私钥生成过程使用类似或重叠的种子 / 状态(如用固定 offset、基于时间戳种子、或多个设备共用 PRNG 实例),攻击者可能在多个地址间找到关联性,交叉推算出私钥。

  4. 加密系统的 RNG 攻击 在更广泛的上下文中,若 RNG 被攻击者控制或篡改(比如植入后门、控制种子输入等),则整个加密系统可能崩盘。Wikipedia 上将此类攻击归为“随机数生成器攻击 (random number generator attack)”的一类(维基百科)。

历史上的真实案例与威胁

下面是一些与加密货币 /私钥 /加密系统中 RNG 弱点有关的真实案例:

  • Randstorm 漏洞 Randstorm 是 2023 年由安全公司 Unciphered 披露的一个问题,影响了在早期使用 JavaScript 端钱包(尤其用 BitcoinJS 库)生成私钥的用户。该漏洞源自随机数生成方式弱、熵不足,导致生成的私钥可被枚举、破解。(Medium) 据称,很多在 2011–2015 年间通过浏览器端 JavaScript 生成的比特币钱包可能受到影响。(Medium)

  • Libbitcoin Explorer (bx seed) 的 “Milk Sad” 漏洞 在 Libbitcoin Explorer 的某些版本(3.0.0 ~ 3.6.0)中,其熵输入机制使用了 mt19937(Mersenne Twister)作为后续随机数生成器,其内部状态被限制为 32 位熵,这大大削弱了随机性。CVE-2023-39910 就指出这个问题:使用该机制生成钱包的私钥可以被远程攻击者恢复。(国家漏洞数据库)

  • Trust Wallet 的低熵问题 有报告指出,Trust Wallet 的浏览器扩展 / iOS 版本等存在使用 mt19937 或其他非安全 PRNG 来生成密钥的缺陷,导致其部分钱包地址被破解。(GitHub)

  • 硬件芯片缺陷(如 ESP32) 最近被报道:ESP32 芯片在某些钱包或设备中用于生成比特币私钥时,其随机数生成模块熵不足,存在私钥预测风险。该漏洞被编号 CVE-2025-27840。(U.Today) 例如,有报道称包含 ESP32 芯片的 Blockstream Jade 硬件钱包也可能因该漏洞受到影响。(CoinGeek)

  • 安卓 / Java SecureRandom 问题 在早年,比特币流行于安卓平台时,有开发者不当使用 Java 的 SecureRandom.setSeed(...) 或其它方式,导致随机性被弱化,从而产生相同或可预测的签名 nonce(导致私钥泄露)的问题。(Cryptography Stack Exchange)

这些案例都表明:即使加密算法本身没有漏洞,但如果随机数生成环节不安全,私钥或签名 nonce 泄露、可预测、可枚举,就足以让攻击者“走捷径”拿到资产。


你(作为用户 / 持有者)的风险与应对

对于普通比特币用户(尤其是自己管理私钥的钱包用户),以下是主要风险和建议:

风险点

  1. 钱包地址被公开列入“弱密钥地址”黑名单 安全社区或研究人员可能已将已知可预测或被破解的地址做成黑名单(或数据库),攻击者可能先扫这个列表中的地址。你如果正好使用了类似的缺陷私钥,就可能被攻击。

  2. 资产被盗而几乎无迹可寻 攻击者通过恢复私钥,一次性将资金转走。因为他们并未破解网络、植入后门,而是“合法地”用私钥转账,几乎不会留下异常入侵痕迹。

  3. 长期隐患 即使漏洞被公开、补丁修复,很多已经生成、仍在使用的钱包将继续受到威胁。对于用户来说,一旦怀疑私钥生成机制有问题,必须及时迁移资产。

  4. 迁移成本和信任问题 将资产迁移到更安全的钱包、生成新的密钥对,是成本(手续费、操作复杂性、信任更换等)。但与丢失数额相比,这个成本微乎其微。

对用户的建议

  • 选用信誉良好、经过安全审计的钱包 尽量选择开源、被广泛使用并定期审计的钱包软件或硬件。这些项目更可能在随机性、加密实现等方面受到社区监督。

  • 避免使用基于浏览器 JS 或 Web 前端生成私钥 浏览器环境、JavaScript 的随机性(尤其旧版)易被攻击者控制或预测。如果必须用这种方式,确保底层随机数接口使用的是 window.crypto.getRandomValues(Web Crypto API)而不是 Math.random()

  • 及时更新软件 / 固件 如果钱包有补丁或更新以加强随机性机制,应尽快升级并重新生成新的密钥或迁移资产。

  • 资产迁移策略 如果怀疑私钥可能受弱随机性影响,应尽快将资产转至全新地址,确保新地址使用强随机性机制生成。

  • 分散风险 / 避免长期托管大额资产在单一地址 虽然这不是随机性问题的根本解决方案,但作为一种风险控制措施,可以降低潜在单点损失。


对开发者 / 钱包实现者的安全建议

作为钱包、加密库的开发者(或参与私钥 /密钥生成、签名过程实现的人),你在随机性(entropy / RNG)方面的设计与实现,可能直接决定用户资产安全。以下是一些关键的安全实践建议:

1. 使用可靠、受信任的 CSPRNG,而不是通用 PRNG

  • 切忌用 random()rand()mt19937、线性同余(LCG)等作为私钥或签名中 nonce 的生成器。这类 PRNG 虽在统计意义上表现良好,但在加密上下文中极易被攻击利用。
  • 在 Python 中,切忌用 random.getrandbits() 来生成私钥,必须使用安全库(如 os.urandom()secrets 模块、cryptography 库提供的随机接口等)。
  • 在 C/C++、Rust、Go、Java 等语言中,应使用其标准库或知名加密库提供的 CSPRNG 接口(例如:Java 的 SecureRandom(但要注意不要手动设置种子)、OpenSSL 的 RAND_bytes、Linux 的 getrandom() / /dev/urandom、libsodium 的随机接口等)。

2. 输入足够的熵,并避免熵萎缩 / 重复使用种子

  • 在程序启动时、或生成密钥之前,应从多种不相关源(如系统随机、硬件随机、时间戳、环境噪声、用户交互等)采集熵,并混合(entropy mixing / stirring)。
  • 避免在资源受限环境(如嵌入式设备、RTOS、低端微控器)里采用简单种子生成方式,或用固定偏移 (offset)、时间戳、设备 ID 等作为种子输入。
  • 如果环境不具备足够熵(如刚启动、虚拟机、无硬件随机器等),应暂停密钥产生操作,直到有足够初始化熵。

3. 不要暴露或允许外部控制种子 / state

  • 禁止给上层调用者功能,让他们“设置”或“指定”种子(除非是安全附加熵输入)。否则会被滥用(如重复种子、固定种子)。
  • 内部状态(如 PRNG 状态、熵池)应严格不被外界读取或泄露。

4. 对 RNG / 密钥生成模块进行安全审计与测试

  • 利用标准随机性测试工具(如 NIST SP 800-22、Dieharder、TestU01 等)测试生成器输出的统计特性(虽然通过统计测试不代表安全,但不通过则肯定有问题)。
  • 对私钥 /地址空间进行黑名单检测:如是否落入已知“弱地址/密钥库”。如发现生成出的地址在弱密钥数据库中,应拒绝并重新生成。
  • 在代码审计、模糊测试、红队测试中重点关注 RNG 模块。

5. 防范侧信道 / 实现泄露

  • 在硬件钱包 /芯片设计中,应避免在 RNG 或混合熵逻辑中出现可测的功耗 /时序 /电磁泄露。
  • 对随机数生成与密钥生成过程做常量时间(constant-time)设计,避免因执行时间差异暴露内部状态。
  • 在嵌入式设备上,慎用复用硬件模块(如 ADC、温度传感器等)作为熵源,必须确保它们在攻击下不会退化。

6. 兼容性与退化策略

  • 若运行环境(某些旧平台、浏览器环境等)不支持高质量随机数接口,应提供 fallback 或警告,禁止在这些环境生成关键密钥。
  • 如果库 /钱包从旧版本升级,应考虑是否需要强制用户重新生成密钥或迁移资产,以避免旧版本遗留弱密钥问题。

用代码示例说明错误与正确方法(以 Python 为例)

下面是一个“错误”用法示例(仅作警示):

import random

# 这段代码极度危险,不要在生产环境用于生成私钥
private_key = hex(random.getrandbits(256))

这是错误的,因为 random.getrandbits() 使用的是 Python 默认的伪随机模块(基于 Mersenne Twister 或类似算法),并非加密安全随机数生成器,其内部状态极易被反推。

正确的做法应使用加密安全的随机接口,例如:

import secrets  # Python 3.6+
private_key = secrets.randbits(256)  # 这是安全的,使用系统 CSPRNG

# 或者借助 cryptography 库
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.backends import default_backend

# 使用库内置的方法生成私钥
priv = ec.generate_private_key(ec.SECP256K1(), default_backend())
# 然后获取其整数形式、序列化等
private_value = priv.private_numbers().private_value

在很多语言 /平台中也有类似的最佳实践:直接调用安全库里的密钥生成接口,而不是自己“拼随机数 + 计算椭圆曲线乘法”。


总结:牢记“随机性是加密的命脉”

  • 虽然比特币、椭圆曲线、签名算法、哈希算法等都极其复杂、强大,但如果随机性环节有缺陷,那么整个安全性可能瞬间崩溃。
  • 最近美国执法部门查获比特币、以及多个钱包实现中被发现的随机性缺陷案例,都警示我们:私钥生成阶段的随机性缺陷会直接导致资产损失
  • 对用户而言,选择经过审计、口碑好、支持强随机性的钱包、及时更新、资产迁移是防范之道。
  • 对开发者而言,在设计、实现、审计 RNG/密钥生成模块时,必须把“安全随机性”放在首位,避免使用非加密 PRNG、不恰当的种子输入、泄露状态等低级错误。

结语:

比特币的安全,不仅取决于数学的坚固,更取决于实现的严谨。一行看似无害的随机数代码,可能埋下价值数百万美元的隐患。密码学的世界没有“差不多”,只有“绝对安全”与“彻底失败”两种结果。对用户而言,选择安全的钱包与及时迁移资产,是防止悲剧重演的唯一途径;对开发者而言,理解并正确实现安全随机性,是守护整个加密生态最基本的职责。让随机数真正“随机”,比特币才能真正安全。