慢雾出品|区块链应用中常见的密码学风险

CN
7小时前

本文经授权转载自慢雾科技,作者:慢雾安全团队,版权归原作者所有。


密码学是 Web3 安全的基石,从私钥的生成到交易的签名,每一个环节都依赖于密码学组件的正确与安全实现。然而,在 Web3 项目的实际开发中,研发团队往往聚焦于业务逻辑与性能优化,对底层密码学实现的细微之处缺乏足够的警惕。使用不安全的随机数生成器、错误地调用密码学库、或对算法特性的理解偏差,都可能引入致命漏洞,导致私钥泄露、签名伪造、进而造成无法挽回的资产损失。


通常,项目方会依赖安全审计来发现此类问题。然而,审计作为一种事后验证手段,难以覆盖项目全生命周期。许多漏洞根植于开发阶段初期选型与设计,若团队自身不具备基础的密码学安全知识,则无法从根源上规避风险。


因此,慢雾安全团队开源了区块链应用中常见的密码学风险,希望将一线攻防中积累的、关于密码学误用的典型案例与最佳实践沉淀下来。我们期望项目方团队能够在开发之初便筑牢密码学安全防线,最终建立起自主、持续的安全编码能力。


1. 使用 JavaScript Math.random 或基于时间的种子生成随机数


严重性:高


描述:JavaScript 的 Math.random() 是一个伪随机数生成器(PRNG),不适合用于加密安全的场景。其实现依赖于浏览器或 JavaScript 引擎(如 V8 的 Xorshift128+),种子和算法通常不可控且不可预测性不足,可能导致生成的随机数序列被攻击者猜测或重现。


利用场景:这在生成加密密钥、会话令牌、CSRF 令牌或游戏随机事件时,可能导致密钥被破解、会话劫持或游戏作弊。


建议:优先使用 crypto.getRandomValues() (Web Crypto API) 生成加密安全的随机数,适用于密钥、令牌等敏感场景。


2. 使用 Java 的不安全随机数生成方式生成私钥


严重性:高


描述:Java 的 java.util.Random 或 java.util.concurrent.ThreadLocalRandom 是非加密安全的伪随机数生成器(PRNG),其种子和算法(如线性同余生成器)可预测且熵不足。如果使用这些方法生成加密私钥(如 RSA、ECDSA),生成的密钥可能存在可预测性,容易被攻击者推导或重现。


利用场景:在基于 Java 的 Web 应用中,使用 Random 生成的密钥可能被攻击者利用,破解 TLS 会话或伪造 JWT 令牌。


建议:改用 java.security.SecureRandom,它是为加密场景设计的随机数生成器,提供高熵输出,适合生成私钥。或者优先使用标准库或框架(如 KeyPairGenerator、KeyFactory)生成密钥。


Android 系统在某些版本中 SecureRandom 未能正确初始化


严重性:高


描述:在某些 Android 版本(特别是早期版本,如 4.1-4.3),java.security.SecureRandom 未能正确初始化,导致其生成的随机数熵不足。这通常是由于系统熵池(如 /dev/urandom)未被充分填充,或者 SecureRandom 的实现缺陷,致使生成的随机数序列可预测性较高,用于私钥生成时显著降低安全性。


利用场景:在受影响的 Android 设备上,使用 SecureRandom 生成的 Bitcoin 私钥可能被破解,导致资金被盗。


建议:在调用 SecureRandom 前,显式调用 SecureRandom.setSeed() 并结合高熵来源(如用户输入或硬件传感器数据)增强随机性。


私钥生成过程中存储随机数的变量类型空间太小


严重性:高


描述:在私钥生成过程中,若使用空间太小的变量类型(如 32 位整数)存储随机数,会限制随机数的范围和熵值,导致生成的私钥强度不足。


利用场景:攻击者可利用随机数范围受限的弱点,通过暴力破解或预计算攻击(如彩虹表),快速猜测私钥。例如,在 Profanity 工具的案例中,攻击者通过分析生成的地址模式,成功破解多个 Ethereum 钱包,窃取大量资金。


建议:使用足够大的变量类型(如 256 位或更高)存储随机数,以支持完整密钥空间(如 secp256k1 曲线的 2^256 范围)。


Libbitcoin Mersenne Twister 弱熵漏洞


严重性:高


描述:Libbitcoin Explorer(版本 3.0.0 至 3.6.0)的 bx seed 命令使用 Mersenne Twister(MT19937) 伪随机数生成器(PRNG) 生成钱包种子,种子仅由 32 位系统时间(high_resolution_clock) 初始化。这导致熵空间被限制在 2^32(约 43 亿)个可能值,远低于安全的 128 位或 256 位熵要求。攻击者可通过暴力破解重现种子,进而推导私钥,危及用户资金安全。此漏洞被称为“Milk Sad”,因其生成的首个种子短语以“milk sad”开头。


利用场景:get_clock_seed() 返回仅 32 位的系统时间戳(uint32_t),用作 Mersenne Twister 的种子。std::mt19937 虽生成看似随机的输出,但其熵受限于 32 位种子,无法提供 128 位或更高安全级别。pseudo_random_fill 填充输出时,扩展到 256 位仅是伪随机扩展,未增加实际熵。


建议:替换 Mersenne Twister,改用加密安全的随机数生成器(如 /dev/urandom、C++ 的 std::random_device 搭配高熵源,或 OpenSSL 的 RAND_bytes)。


6. OpenSSL 随机数生成器安全风险


严重性:高


描述:OpenSSL 密码库的随机数生成器 RAND_pseudo_bytes() 用于将 num 伪随机字节放入 buf,但存在安全设计缺陷。由 RAND_pseudo_bytes() 生成的伪随机字节序列如果长度足够长,则是唯一的,但并不一定是不可预测的。它们可以用于非加密目的,并且可以在某些加密协议中用于特定目的,但通常不用于密钥生成等。


漏洞示例:低熵密钥泄露(LESLI),即攻击者通过获取 nonce 并通过暴力枚举所有可能的 PIN 码和 RNG 状态,可以恢复原始的 PIN 值。


建议:避免使用 RAND_pseudo_bytes,完全替换为 RAND_bytes 并检查其返回值。


1. secp256r1 后门问题


严重性:中


描述:secp256r1(也称 NIST P-256)是一种广泛使用的椭圆曲线密码算法,但存在对其生成参数潜在后门的担忧。标准化过程中,参数由 NSA 提供,缺乏透明的生成过程,可能被故意设计为包含弱点,允许特定攻击者(如 NSA)利用隐藏的数学关系解密数据或伪造签名。


利用场景:攻击者可能利用后门(若存在)通过已知参数的数学特性,快速计算私钥或预测随机数生成器的输出,从而破解加密通信、伪造数字签名,或窃取基于 secp256r1 的加密系统(如 TLS、Bitcoin、SSH)中的敏感数据。


建议:考虑切换到 Ed25519 或 Secp256k1 等透明生成参数的曲线,降低后门风险。


2. secp256k1 中 k 值弱随机导致私钥泄露


严重性:高


描述:在 secp256k1 曲线的 ECDSA 签名过程中,签名需要一个随机数 k (nonce)。如果 k 值由弱随机数生成器生成(例如,低熵源、不安全的 PRNG 或可预测的种子),攻击者可能通过分析签名数据推测 k 值,进而利用 ECDSA 的数学特性直接计算私钥。这种漏洞通常源于使用不安全的随机数生成器(如 rand()、Math.random())或环境熵不足(如虚拟机或嵌入式设备)。


利用场景:攻击者可通过收集少量签名数据(例如,r 和 s 值),结合弱随机数的可预测性,重构 k 值并推导私钥。在区块链场景(如 Bitcoin、Ethereum),这可能导致钱包私钥暴露,资金被盗。例如,若 k 值基于时间戳或固定种子生成,攻击者可通过暴力破解或模式分析快速恢复私钥。类似问题曾出现在早期加密钱包实现中,因使用弱随机源生成 k 值而被破解。


建议:使用确定性 k 值生成(RFC 6979),基于私钥和消息哈希生成唯一的 k 值,避免依赖随机数生成器的质量。


3. secp256k1 中 k 值重用导致私钥泄露


严重性:高


描述:在 secp256k1 椭圆曲线(广泛用于比特币等加密货币)上使用 ECDSA 签名时,如果两次签名使用了相同的随机数 k (nonce),则签名中的 r 值将相同。攻击者可通过分析这两组签名(r, s1) 和(r, s2) 及对应的消息哈希 h1、h2,推导出私钥。这种漏洞源于 ECDSA 签名方程的数学结构,k 的重用使得攻击者能够建立方程组,直接解出私钥 d。


建议:遵循 RFC 6979 标准,根据私钥和消息哈希生成确定性但不可预测的 k 值,防止重用。


4. ECDSA 签名值的可锻造性


严重性:中


描述:ECDSA(椭圆曲线数字签名算法)的签名值(r, s) 存在可锻造性,即给定一个有效签名(r, s),可以生成另一个等价的有效签名(r, -s mod n),其中 n 是椭圆曲线的阶。这种数学特性源于 ECDSA 签名验证的模运算对称性。如果实现未规范化签名(例如,强制使用“低 s 值”),攻击者可修改签名而不影响其有效性,可能绕过签名验证机制或破坏某些协议的唯一性要求。


利用场景:攻击者可利用签名可锻造性在区块链(如 Bitcoin、Ethereum)或协议中制造问题。例如,在 Bitcoin 交易中,攻击者可修改交易签名的 s 值生成新签名,改变交易 ID (txid),导致交易被拒绝或引发双花风险。此外,在某些智能合约或多重签名协议中,未规范化签名可能被用来绕过验证逻辑,造成资金损失或协议失效。2013 年,Bitcoin 网络曾因签名可锻造性引发交易可塑性(malleability) 攻击,影响 Mt. Gox 等交易所。


建议:强制使用“低 s 值”(s ≤ n/2),遵循 RFC 6979 或 BIP-66 标准(Bitcoin 社区采用),拒绝非规范签名以消除可锻造性。


5. ECDSA 与 Schnorr 签名共用随机数 k 导致私钥泄露


严重性:高


描述:在椭圆曲线数字签名算法(ECDSA) 和 Schnorr 签名中,如果在生成签名时共用相同的随机数 k (nonce),攻击者可以通过分析签名来推导出私钥。这种漏洞源于两种签名方案的数学结构相似性,允许通过已知的签名方程反推出私钥。无论是在同一系统内多次签名,还是在不同签名算法间重用 k,都会导致私钥完全暴露,进而使攻击者能够伪造签名或控制相关账户。


建议:RFC6979 中输⼊参数可以包含“addition data”,在派⽣ k 时,可以将签名算法的信息填⼊该字段,如此可以在算法的维度上安全重⽤ k。


6. ECDSA 不需要提供签名值对应的消息 m 时可伪造签名值


严重性:低


描述:在验证 ECDSA 签名时,若验证过程仅要求提供消息的哈希值而非原始消息本身,则攻击者可以在不知道私钥的情况下,基于已知的合法签名,构造出能通过验证的伪造签名。这个漏洞利用了 ECDSA 验证机制的数学特性,允许攻击者选择特定的数值组合创建伪造签名,而无需知道对应的原始消息或私钥。


建议:验证签名时必须要求提供原始消息 m,而不仅仅是哈希值。


7. ECDSA 签名中的 Nonce 侧信道攻击漏洞


严重性:高


描述:LadderLeak 是一种存在于 ECDSA 实现中的侧信道漏洞,攻击者可以通过缓存时序分析获取签名过程中使用的随机数(nonce) 的最高有效位信息,但泄露概率低于 100%(即"不到 1 比特"的信息)。该漏洞存在于 OpenSSL 1.0.2 和 1.1.0 分支以及 RELIC 工具包 0.4.0 版本中,特别影响了基于曲线 sect163r1 和 NIST P-192 的 ECDSA 实现。该漏洞源于 Montgomery 梯形算法实现中坐标处理不当导致的微小时间差异。攻击者可以观察到这种时间差异,并利用统计方法推断出随机数 k 的最高位。即使这种泄露率低于 100%(如对 P-192 为 99%,对 sect163r1 为 97.3%),攻击者仍然可以通过改进的 Bleichenbacher 傅立叶分析方法,收集足够数量的签名后完全恢复私钥。


漏洞示例:针对 OpenSSL 的实现,漏洞表现在二进制曲线情况(如 sect163r1)和素数曲线情况(如 NIST P-192)两种情况下。研究人员利用这种泄露,对 P-192 实现了完全私钥恢复,只需要约 2³⁵ 个签名;对 sect163r1 则仅需要约 2²⁴ 个签名。这显著突破了以往攻击技术的限制,以往至少需要 2 比特泄露才能实现可行的攻击。


建议:坐标随机化。


8. 椭圆曲线密码学中的扭曲曲线攻击漏洞


严重性:高


描述:椭圆曲线密码学(ECC) 实现中存在一类严重的安全漏洞,称为"扭曲曲线攻击"(twist attacks)。这类攻击利用了椭圆曲线的数学特性和实现中的安全缺陷,允许攻击者在特定条件下提取出受害者的私钥。特别是在使用单坐标梯形算法(如 Montgomery 梯形算法)实现 Diffie-Hellman 密钥交换时,如果未采取适当的防御措施,攻击者可能会成功获取私钥信息。


建议:验证接收的点是否确实位于预期的曲线上。


1. Ed25519 签名算法中的私钥提取漏洞


严重性:高


描述:该漏洞存在于 Ed25519 签名算法库的实现中,主要由于一些库设计上的缺陷以及用户对算法库接口的错误使用导致。攻击者可以通过操控两次签名过程,使用同一私钥但不同公钥对同一消息进行签名,然后通过分析这两次签名的结果,直接提取出用户的完整私钥。在标准实现中,签名计算应该使用与私钥对应的唯一公钥。然而,许多库实现了形如 sign (privateKey,message, publicKey) 的接口,允许调用者提供任意公钥参数,而没有验证该公钥是否与提供的私钥匹配。这一缺陷结合 Ed25519 签名算法中使用确定性随机数的特性,使得攻击者可以通过两次签名,消除签名过程中的确定性不变量,从而提取出可用于签名的私钥扩展值,进而获取到完整的私钥控制权。此漏洞影响所有提供了这种不安全接口且未进行公钥验证的 Ed25519 实现库,包括可能用于移动端钱包、硬件钱包和云钱包的各种场景。类似的攻击方式也适用于 Schnorr 签名算法。


建议:不要提供形如 sign (privateKey, message, publicKey) 的接口,应只提供 sign (privateKey, message) 接口,内部通过私钥计算对应公钥。


2. Ed25519 签名算法在 WolfSSL 中的侧信道漏洞


严重性:高


描述:Ed25519 是一种椭圆曲线数字签名算法(EdDSA),其设计初衷是避免 ECDSA 中必须使用高质量随机数的缺点。Ed25519 通过从消息和辅助密钥确定性地派生临时密钥(ephemeral key),旨在消除随机数生成的风险。然而,研究表明这种确定性设计在侧信道攻击环境中反而引入了新的漏洞。在 WolfSSL 库的 Ed25519 实现中发现了严重的电力分析漏洞,攻击者只需收集约 4,000 个签名操作的电力轨迹,就能完全恢复私钥。漏洞来源于确定性地生成临时密钥过程中使用的 SHA-512 哈希函数,攻击者可以利用差分功耗分析(DPA) 来提取密钥信息。具体来说,SHA-512 消息调度功能中使用的模加法操作由于其非线性特性产生可观测的侧信道泄漏。这一漏洞对使用 WolfSSL 实现 Ed25519 的 IoT 设备和嵌入式系统构成严重威胁,因为这些设备通常更容易受到物理访问和侧信道攻击。


建议:修改 Ed25519 实现,在计算临时密钥时添加一个随机值,使得攻击者无法预测哈希函数的输入。确保整个第一个 1024 位数据块仅包含密钥和随机值,而不包含攻击者已知的任何位。


3. Ed25519 曲线余因子不为 1 引发的双花漏洞


严重性:高


描述:Edwards25519 椭圆曲线具有余因子(Cofactor) 为 8 的特性,这意味着曲线上的点群结构包括一个大素数阶子群 G1 和一个阶为 8 的小阶子群 G2。在基于 Edwards25519 构建密码协议(如环签名和 RingCT)时,如果未正确处理这种余因子不为 1 的情况,可能导致严重的双花甚至多花攻击。此漏洞源于验证过程中未能确保 key image(用于防止双花的关键组件)属于正确的子群,使得攻击者可以构造特殊的交易,使同一笔资金能被重复花费多次。影响了所有基于 CryptoNote 协议且使用 Edwards25519 曲线的加密货币项目。


建议:对所有 key image 实施子群成员检查,确保它们属于大素数阶子群 G1。


4. Ed25519 历史版本中的可延展性漏洞


严重性:中


描述:Ed25519 算法本身满足选择消息攻击的安全性,但可延展性问题允许攻击者修改现有签名生成新的有效签名,可能导致假设签名唯一性的系统出现漏洞(如重复验证或篡改检测失败)。在标准 RFC 8032 中已修复,但旧实现(如 ed25519-dalek 1.0.1 版本)仍存在风险。


漏洞示例:在 Ed25519 签名中,签名由(R, s) 组成,其中 s 是一个标量。如果攻击者获得一个有效签名(R, s) 对应消息 M 和公钥 A,他们可以构造新签名(R, s'),其中 s' = s + l(l 是子群的阶,为素数 2^252 + 27742317777372353535851937790883648493)。由于群的模运算性质,验证方会验证 s' * B == R + h * A(其中 h = Sha512(R || A || M),B 是基点),这与原签名等价,导致新签名也被接受。例如,如果原 s = 123,则 s' = 123 + l 也会通过验证,但签名不再唯一。


建议:在签名验证过程中,按照 RFC 8032 标准添加检查,确保 s < l(群的阶)。如果 s >= l,则拒绝签名。


1. Schnorr Nonce 重用或不良随机数生成


严重性:高


描述:Schnorr 签名的安全性高度依赖于随机数(nonce,k) 的唯一性和不可预测性。如果在不同签名中重用相同的 nonce,攻击者可以通过数学计算恢复私钥。这种问题在理论上被广泛讨论,但在 Schnorr 签名的实际应用中尚未有公开的案例。


漏洞示例:虽然不是 Schnorr 签名本身,ECDSA(与 Schnorr 签名有相似数学基础)在比特币和以太坊中有过因 nonce 重用导致私钥泄露的事件。例如,2010 年代早期,一些比特币钱包因随机数生成器缺陷导致 nonce 重用,进而被黑客利用窃取资金。Schnorr 签名在比特币的 Taproot 升级(2021 年引入)中开始使用,由于其实现遵循严格的 BIP-340 规范(如确定性 nonce 生成),目前未见类似问题。


建议:使用确定性 nonce 生成(如 RFC 6979)或加密安全的随机数生成器。


2. Schnorr 相关密钥攻击


严重性:低


描述:2015 年的一篇学术论文分析了 Schnorr 签名和 DSA 在相关密钥攻击下的安全性。研究表明,标准 Schnorr 签名方案在面对 RKA(攻击者可以操纵签名密钥并获取修改后的签名)时不满足完全的 RKA 安全性,存在理论上的攻击方法。例如,攻击者可能通过篡改密钥生成伪造签名。然而,该研究也提出,通过对 Schnorr 签名方案进行轻微修改(如调整签名生成方式),可以实现完全的 RKA 安全性。


漏洞示例:这不是实际攻击事件,而是理论分析,表明在特定侧信道攻击场景(如篡改设备)下,Schnorr 签名可能面临风险。


建议:在实现中加入密钥完整性检查或使用抗 RKA 的变种方案。


3. Schnorr 侧信道攻击


严重性:低


描述:理论上,Schnorr 签名的实现可能受到侧信道攻击(如时间攻击、功率分析或电磁泄露)的威胁。这些攻击利用签名生成过程中的物理信息泄露来推导私钥或 nonce。


漏洞示例:尽管学术界对此有广泛研究,但没有公开的 Schnorr 签名相关侧信道攻击事件。


建议:实现恒定时间运算、使用抗侧信道的硬件或算法。


1. Filecoin BLS 签名验证中的可延展性漏洞


严重性:高


描述:在 Filecoin 的 Lotus 实现中发现了 BLS 签名验证存在可延展性漏洞。BLS 签名可以以序列化(serialized) 和压缩(compressed) 这两种不同的形式表示,这两种形式都可以通过 BLST 库的 VerifyCompressed 方法成功验证。但 Lotus 的区块验证逻辑使用包含签名的区块头 CID 来识别区块唯一性,这导致了以下安全问题:同一个区块如果使用两种不同形式的 BLS 签名,将被视为两个不同的区块,因为它们的 CID 不同。攻击者可以通过提交包含相同内容但签名格式不同的区块来利用这一漏洞,绕过重复区块检测,可能导致区块链分叉、双花攻击或共识故障。


建议:在验证签名之前,将所有签名转换为统一格式(要么全部使用序列化格式,要么全部使用压缩格式)。


2. BLS 库中的零值相关漏洞与"零值分裂"攻击


严重性:高


描述:研究人员在四个主流 BLS (Boneh-Lynn-Shacham) 加密库和 BLS 标准草案中发现了一系列与零值处理相关的严重安全漏洞,被统称为"splitting zero"(零值分裂)攻击。这些漏洞源于对加密算法中特殊值"0"处理的缺陷,可能导致签名验证绕过、私钥恢复、拒绝服务和其他严重安全问题。特别值得注意的是,GitHub 报告还提到了一些额外的零值相关漏洞,包括:在 supranational/blst 库中,零长度签名或零长度消息会导致程序崩溃;在模 p 运算中,inverse(0) mod p = 0,但 inverse(p) mod p = 1 的处理错误。BLS 签名方案因其独特的聚合特性而广泛应用于区块链和分布式系统,这些漏洞可能对依赖这些库的大型系统产生重大安全影响。


漏洞示例:根据研究文档,“零值分裂”攻击主要包括零签名验证绕过、零公钥攻击、库崩溃漏洞、模运算中的零值问题,以及聚合签名中的零值操纵。


建议:明确定义并一致实现对零值(零长度输入、零点、零标量等)的处理策略。


3. BLS 多重签名中的 Rogue Key Attack 漏洞


严重性:高


描述:在 BLS 签名方案中,聚合公钥和签名仅通过简单求和实现。攻击者可以创建“rogue key”(流氓密钥),通过设置秘密密钥为 0 并计算诚实密钥的加法逆来抵消诚实参与者的贡献。


建议:实施 Proof-of-Possession (PoP) 机制的严格验证,避免依赖简单求和聚合;考虑使用非线性化聚合或额外随机性。


1. RSA 密钥长度过小


严重性:中


描述:RSA 的密钥长度(通常以位数表示,例如 1024 位、2048 位)决定了 n 的大小,从而影响因子分解的计算复杂度。如果密钥位数过少(如 512 位或更低),攻击者可以使用现代计算资源(如高性能计算机或分布式计算网络)相对容易地分解 n 的因子,进而推导出私钥。


建议:NIST 建议至少使用 2048 位 RSA 密钥;对于高安全需求,可用 3072 位或 4096 位。


2. RSA 密钥生成中的近似质数漏洞


严重性:高


描述:RSA 加密算法的安全性依赖于大整数分解问题的计算困难性,其中模数 n 是两个大质数 p 和 q 的乘积。当 p 和 q 选择太过接近时,会产生严重的安全漏洞,使得 n 的因式分解变得显著容易,从而可能导致 RSA 私钥被恶意攻击者恢复。这一漏洞源于费马分解法(Fermat's factorization method) 及其变种算法可以高效地分解两个因子接近的合数。当 p 和 q 非常接近时,它们的平均值 √(pq) 非常接近于 (p+q)/2,可以通过尝试 (p+q)/2 附近的值来进行有效的因式分解。


漏洞示例:具体来说,如果 |p-q| 较小,可以定义整数值 s = (p+q)/2和d = (p-q)/2,那么 p = s+d,q = s-d,且 n = pq = s²-d²。这转化为寻找 n+d² 是否为完全平方数。当 p 和 q 接近时,d 值较小,使得这种搜索效率非常高。


建议:遵循 NIST 标准(如 FIPS 186-4),要求 |p-q| > 2^(nlen/2-100),其中 nlen 是模数 n 的位长;对于 2048 位 RSA 密钥,p 和 q 的差值应至少为 2^924 位;考虑 |p-q| > 2^(nlen/2) 和 |p-(n/p)| > 2^(nlen/2) 等更严格的标准。


3. RSA 模数重用漏洞


严重性:极高


描述:RSA 加密的安全性基于大整数因式分解问题的困难性,其中模数 n 是两个大质数 p 和 q 的乘积。在正常的 RSA 实现中,每个密钥对应具有唯一的模数 n 和相应的唯一公钥指数 e 与私钥指数 d。当模数 n 被重用时,即使使用不同的公钥指数 e 和私钥指数 d,只要攻击者获得了多个使用相同模数的公钥,就可以通过简单的数学计算恢复私钥。


建议:每次生成 RSA 密钥对时必须生成新的模数 n;禁止在不同的密钥对、用户或系统间共享模数。


4. RSA 小公钥指数漏洞


严重性:高


描述:RSA 算法的安全性建立在大整数因式分解的计算困难性上,其中公钥由模数 n(两个大质数 p 和 q 的乘积)和指数 e 组成,而私钥主要由指数 d 组成,满足 e·d ≡ 1 (mod φ(n))。当选择极小的 e 值时,特别是 e=3,虽然加密操作简化为计算 c = m³ mod n,但会引入数学弱点。


漏洞示例:这类漏洞主要体现在直接开方攻击、Håstad 广播攻击、Coppersmith 相关消息攻击和 Bleichenbacher 填充攻击上。在实际应用中尤为危险,因为许多开发者可能为了提高性能而选择小指数,尤其是在资源受限的环境中,且可能不了解或忽视相关的安全风险。


建议:避免使用 e=3、e=5 或其他极小值;推荐使用 e=65537 (2^16+1),这是一个较大的素数,同时仍保持合理的性能。


5. RSA 小私钥指数漏洞


严重性:高


描述:RSA 算法的安全性建立在大整数因式分解问题的计算困难性上,其中公钥由模数 n(两个大质数 p 和 q 的乘积)和公钥指数 e 组成,私钥主要由指数 d 组成,满足 ed ≡ 1 (mod φ(n))。私钥指数 d 用于解密和签名操作,其计算复杂度与 d 的大小成正比。当使用过小的私钥指数 d 时,即使模数 n 非常大,整个加密系统也可能被破解。这种漏洞使攻击者能够在不进行困难的整数因式分解的情况下,通过数学方法恢复私钥,从而完全破坏 RSA 的安全保证。


漏洞示例:为了提高解密和签名效率,某些实现可能会刻意选择较小的 d 值,这会导致几种严重的数学攻击,如 Wiener 攻击、Boneh-Durfee 攻击和部分密钥泄露攻击。


建议:使用充分大的私钥指数 d。确保 d 至少与 φ(n) 同等量级,避免刻意选择小的 d 值。实际上,随机选择 e 通常会导致 d 与φ(n) 同阶,这是安全的。


6. RSA 无填充短消息攻击漏洞


严重性:高


描述:当使用 RSA 直接加密消息 m 时,加密过程计算 c = m^e mod n,其中 e 是公钥指数,n 是模数。如果原始消息 m 相对于模数 n 非常小(m << n),则 m^e 可能小于 n,导致 c = m^e 而不是 c = m^e mod n。在这种情况下,攻击者可以简单地计算 m = c^(1/e)(即对密文 c 开 e 次方根)直接恢复原始消息,而无需知道私钥。


建议:实现 RSA 加密时使用 PKCS#1 v2.1 OAEP(最优非对称加密填充),它添加随机性并扩展消息大小。


7. RSA 填充预言机攻击漏洞


严重性:高


描述:在 RSA 加密中使用 PKCS#1 v1.5 填充时,如果服务器在解密无效填充的密文时返回特定错误信息(例如,“无效填充” vs. “其他错误”),这就形成了“填充预言机”。攻击者可以反复发送修改后的密文,观察响应来缩小明文范围。


漏洞示例:攻击者截获一个有效的 RSA 密文 c(加密了明文 m)。他们生成变体密文 c' = (c * 2^e) mod N,并发送到服务器。根据服务器是否报告填充有效,攻击者使用 Bleichenbacher 算法逐步恢复 m。这在 1998 年的 Bleichenbacher 攻击中被证明有效,曾影响 SSL/TLS 实现,导致如 2014 年 ROBOT 攻击的变体。


建议:确保 RSA 解密和填充验证过程在时间上和返回信息上不泄露信息。


8. RSA 计时攻击漏洞


严重性:高


描述:RSA 计时攻击是一种侧信道攻击,攻击者通过精确测量 RSA 操作(如解密或签名)的执行时间差异,能够逐步推导出私钥信息,从而完全破解 RSA 密码系统。即使 RSA 算法本身在数学上是安全的,其实现方式可能导致这种严重漏洞。这类攻击主要利用了 RSA 私钥操作中的模幂运算(m^d mod n) 通常使用的"平方乘"(square-and-multiply) 或"蒙哥马利归约"(Montgomery reduction) 等算法。在这些算法中,处理时间会根据私钥 d 的比特模式而变化。例如,在基本的平方乘算法中,当私钥比特为 1 时会执行额外的乘法操作,而比特为 0 时则不会,这导致可测量的时间差异。


漏洞示例:攻击者通过发送精心选择的消息并测量处理时间,可以推断出私钥 d 的每一个比特。随着足够多的测量样本,攻击者能够完全重建私钥,从而可以解密所有通信或伪造数字签名。


建议:确保 RSA 操作在固定时间内完成,无论私钥比特模式如何。使用原生支持常量时间操作的密码库。


9. RSA 延展性攻击漏洞


严重性:高


描述:RSA 加密具有乘法延展性,如果 c = m^e mod N,则对于任意 k,c' = (c * k^e) mod N 解密为 m * k mod N。攻击者可以利用此特性操纵密文而不触发解密错误。


漏洞示例:假设一个加密的银行转账消息 m = "转账 100 元",密文 c = m^e mod N。攻击者计算 c' = c * (2^e) mod N,解密后变为"转账 200 元"。这在不带签名的协议中有效,如早期电子现金系统或自定义加密方案中,曾在实际攻击中被利用,例如修改加密的投票或金融数据,导致如 2010 年代的一些区块链或协议漏洞。


建议:结合使用数字签名(如 RSA-PSS)或消息认证码(MAC) 来验证消息完整性,防止篡改。


1. 哈希碰撞生日攻击


严重性:高


描述:哈希生日攻击基于概率学中的"生日悖论",利用这一原理可以大幅降低找到哈希碰撞所需的计算复杂度。对于 n 比特的哈希函数,理论上需要 2^n 次尝试才能找到特定的碰撞,但利用生日攻击,只需约 2^(n/2) 次尝试就能找到任意两个输入产生相同哈希值的概率达到 50%。


漏洞示例:假设使用 MD5 哈希函数(128 位输出),攻击者可以通过生成约 2^{64} 个变体消息来找到碰撞。例如,攻击者创建两个不同合同文件 A 和 B(A 是合法的,B 是篡改的),使得 MD5(A) = MD5(B)。如果系统使用 MD5 验证签名,攻击者可以用 A 的签名伪造 B,导致如 2004 年 Flaming 攻击中 MD5 碰撞用于生成假证书,或 2012 年 Flame 恶意软件利用碰撞绕过 Windows 更新验证。


建议:采用抗碰撞性强的现代哈希算法,如 SHA-256、SHA-3 或 BLAKE2,避免使用 MD5 和 SHA-1 等已被证明不安全的算法。


2. 哈希函数长度扩展攻击


严重性:高


描述:哈希函数长度扩展攻击(Length Extension Attack) 是一种针对使用 Merkle-Damgård 结构的哈希函数(如 MD5、SHA-1和 SHA-2 系列)的密码学攻击。攻击者利用这类哈希函数的内部工作机制,在知道 H(message) 和 message 长度的情况下,无需知道 message 本身,就能够计算出 H(message||padding||extension) 的值,其中 extension 是攻击者选择的任意数据。这种攻击之所以可行,是因为 Merkle-Damgård 结构的哈希算法将输入分割为固定长度的数据块,并且每个块的哈希值依赖于前一个块的哈希状态。这意味着攻击者可以从一个已知的哈希状态继续计算,添加更多数据块,而无需知道产生该状态的原始数据。这类漏洞在 Web 应用、API 验证、身份认证系统和区块链应用中尤为危险,特别是当系统使用形如 H(secret||message) 的简单验证模式时。


建议:采用 SHA-3、BLAKE2 等非 Merkle-Damgård 结构的现代哈希算法,这些算法天然不受长度扩展攻击影响。


1. AES AES 加密密钥长度不足


严重性:高


描述:标准 AES 支持 128 位、192 位和 256 位密钥。如果使用的密钥长度过低(例如低于 128 位,如 56 位或更低),加密将变得脆弱,攻击者可以通过暴力破解(brute-force attack) 或字典攻击等方式快速解密数据。这可能导致敏感信息泄露、数据篡改或系统入侵,尤其在现代计算环境中,高性能 GPU 和分布式计算可以加速破解过程。


漏洞示例:根据 NIST(美国国家标准与技术研究院)指南,低于 128 位的密钥长度已被视为不安全,无法抵御当代威胁。


建议:始终采用至少 128 位的 AES 密钥,优先考虑 256 位以提供更高安全性。避免自定义或低于标准的长度。


2. AES 中的 IV/Nonce 重用攻击


严重性:高


描述:IV/Nonce 重用攻击是针对 AES 加密模式的一种严重安全威胁。当在相同密钥下重复使用初始化向量(IV) 或一次性数字(Nonce) 时,会导致严重的安全问题。在 CTR 模式下,重用会产生相同的密钥流,攻击者可以通过密文的 XOR 运算直接获得两个明文的 XOR 结果,进而通过频率分析等方法恢复原始明文。在 GCM 模式下,Nonce 重用不仅会泄露明文信息,还会完全破坏认证机制,允许攻击者伪造认证标签。在 CBC 模式下,虽然影响相对较小,但仍会泄露相同明文块的信息。这种攻击的危险性在于它不需要获取密钥,仅通过观察密文模式就能推断明文内容,在某些情况下甚至能够完全恢复密钥。


漏洞示例:最典型的案例是 2016 年发现的 Android 加密漏洞,其文件系统加密使用了 AES-CBC 模式但 IV 生成存在缺陷,导致相同文件内容在不同时间加密时可能产生相同的 IV,从而泄露文件模式信息。另一个著名例子是某些 WPA2 实现中的密钥重装攻击(KRACK),攻击者通过重放握手消息强制重用 Nonce,导致 AES-CCMP 加密流被破解。在 Web 应用中,一些开发者错误地使用固定的 IV 或基于时间戳的可预测 IV 来加密用户数据,导致攻击者能够通过比较不同用户的加密数据来推断敏感信息。云存储服务中也曾出现过类似问题,由于去重机制的设计缺陷,相同文件可能使用相同的加密参数,导致数据泄露。


建议:应确保每次加密操作都使用唯一且不可预测的 IV/Nonce。


3. AES-ECB 模式弱加密风险


严重性:高


描述:电子密码本模式(ECB - Electronic Codebook) 是 AES 加密的一种操作模式,存在严重的安全隐患。ECB 模式的主要缺陷在于它对相同的明文块总是生成相同的密文块,而不考虑块在消息中的位置或之前加密的内容。这种确定性的加密模式导致加密后的数据仍然保留了原始数据的模式和结构特征,无法提供现代密码学所要求的语义安全性。在 ECB 模式下,密文可能会泄露明文的模式信息,使攻击者能够在不知道密钥的情况下推断部分或全部明文内容。这种弱加密模式尤其不适合加密较大的数据集、结构化数据或包含重复信息的数据。


漏洞示例:使用 ECB 模式加密图像时,图像的轮廓和主要特征在加密后仍然可见。经典例子是 ECB 企鹅图像,即使经过"加密",企鹅的轮廓依然清晰可辨。


建议:除非是加密单个块且小于块大小(16 字节)的数据,否则应完全避免使用 ECB 模式。


4. AES-CBC 密文填充攻击


严重性:高


描述:AES-CBC 密文填充攻击(Padding Oracle Attack) 是一种针对使用 CBC 模式的对称加密系统的侧信道攻击。该攻击利用解密系统在验证填充时泄露的信息,允许攻击者在不知道加密密钥的情况下逐字节解密密文。当加密系统返回关于填充是否有效的任何信息(如错误消息、返回代码或响应时间差异)时,攻击者可以通过有系统地修改密文并观察系统响应,逐步推导出原始明文内容。攻击原理基于 CBC 模式的解密特性,当密文被解密时,前一个密文块会与当前解密后的块进行异或操作。通过精心构造并修改密文块,攻击者可以利用填充验证机制作为"Oracle"(预言机),从而推断出解密后的中间值,最终恢复出完整的明文数据。此外,通过 CBC-R (CBC Reverse) 技术,攻击者甚至可以伪造能被系统正确解密的密文。


漏洞示例:历史上多个 TLS 实现受到此类攻击,如 POODLE(2014 年)和"幸运十三"(2013 年)攻击。攻击者可以通过拦截加密通信,修改密文并分析服务器响应,最终破解加密内容。


建议:采用 AEAD(带关联数据的认证加密)密码模式,如 AES-GCM 或 ChaCha20-Poly1305。


1. 弱 Fiat-Shamir 变换


严重性:高


描述:Fiat-Shamir 变换是将交互式的零知识证明协议转化为非交互式的证明协议的一个重要方法,它将证明者和验证者中的随机挑战替换成散列函数的输出⁠。冰心漏洞(Frozen Heart) 是指在实现 Fiat-Shamir 变换时,使用了"弱 Fiat-Shamir"变换,即只对证明者的部分消息进行散列而不散列公开信息(如参数、公开输入等)。这导致攻击者可以在不知道秘密值的情况下,通过预计算公钥 A 来伪造证明,欺骗验证者。该漏洞影响了多个主流零知识证明系统,包括 Bulletproofs、Plonk、Spartan 和 Wesolowski 的 VDF 等。


建议:确保在 Fiat-Shamir 变换实现中,将所有公共输入数据也加入到随机数生成过程中。


2. GG18 和 GG20 Paillier 密钥漏洞


严重性:高


漏洞描述:该漏洞存在于两个广泛使用的多方计算(MPC) 协议 GG18 和 GG20 的规范中,影响了超过 10 个钱包和库(包括币安托管服务)。漏洞的根源在于协议实现中未检查攻击者的 Paillier 模数 N 是否包含小因子或是否为双素数。攻击者可以利用此漏洞与 MPC 协议中的签名方交互,窃取他们的秘密分片并最终获得主秘密密钥,从而完全提取私钥并盗取加密钱包中的所有资金。


建议:确保签名方的 Paillier 公钥经过小素数因子检查,防止攻击者使用包含小因子(如 2^20 大小的素数)的恶意模数。


慢雾安全团队开源——区块链应用中常见的密码学风险,旨在系统性地揭示私钥生成、数字签名、哈希函数及对称加密等核心环节中潜藏的高危安全风险。Web3 项目方可以参考本文对各类漏洞的原理剖析、利用场景及修复建议,深化对密码学安全的理解,规避常见的实现陷阱,从而更有效地保障项目和用户的资产安全。


相关推荐:闪崩测试下的市场韧性:ADL机制如何守护资金安全


原文: 《 慢雾出品|区块链应用中常见的密码学风险 》

免责声明:本文章仅代表作者个人观点,不代表本平台的立场和观点。本文章仅供信息分享,不构成对任何人的任何投资建议。用户与作者之间的任何争议,与本平台无关。如网页中刊载的文章或图片涉及侵权,请提供相关的权利证明和身份证明发送邮件到support@aicoin.com,本平台相关工作人员将会进行核查。

分享至:
APP下载

X

Telegram

Facebook

Reddit

复制链接