本文經授權轉載自慢霧科技,作者:慢霧安全團隊,版權歸原作者所有。

背景概述

密碼學是 Web3 安全的基石,從私鑰的生成到交易的簽名,每一個環節都依賴於密碼學組件的正確與安全實現。然而,在 Web3 項目的實際開發中,研發團隊往往聚焦於業務邏輯與性能優化,對底層密碼學實現的細微之處缺乏足夠的警惕。使用不安全的隨機數生成器、錯誤地調用密碼學庫、或對算法特性的理解偏差,都可能引入致命漏洞,導致私鑰洩露、簽名偽造、進而造成無法挽回的資產損失。

通常,項目方會依賴安全審計來發現此類問題。然而,審計作為一種事後驗證手段,難以覆蓋項目全生命周期。許多漏洞根植於開發階段初期選型與設計,若團隊自身不具備基礎的密碼學安全知識,則無法從根源上規避風險。

因此,慢霧安全團隊開源了區塊鏈應用中常見的密碼學風險,希望將一線攻防中積累的、關於密碼學誤用的典型案例與最佳實踐沉澱下來。我們期望項目方團隊能夠在開發之初便築牢密碼學安全防線,最終建立起自主、持續的安全編碼能力。

0x01 私鑰隨機數安全

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)生成密鑰。

3.Android 系統在某些版本中 SecureRandom 未能正確初始化

  • 嚴重性:高

  • 描述:在某些 Android 版本(特別是早期版本,如 4.1-4.3),java.security.SecureRandom 未能正確初始化,導致其生成的隨機數熵不足。這通常是由於系統熵池(如 /dev/urandom)未被充分填充,或者 SecureRandom 的實現缺陷,致使生成的隨機數序列可預測性較高,用於私鑰生成時顯著降低安全性。

  • 利用場景:在受影響的 Android 設備上,使用 SecureRandom 生成的 Bitcoin 私鑰可能被破解,導致資金被盜。

  • 建議:在調用 SecureRandom 前,顯式調用 SecureRandom.setSeed() 並結合高熵來源(如用戶輸入或硬體傳感器數據)增強隨機性。

4.私鑰生成過程中存儲隨機數的變量類型空間太小

  • 嚴重性:高

  • 描述:在私鑰生成過程中,若使用空間太小的變量類型(如 32 位整數)存儲隨機數,會限制隨機數的範圍和熵值,導致生成的私鑰強度不足。

  • 利用場景:攻擊者可利用隨機數範圍受限的弱點,通過暴力破解或預計算攻擊(如彩虹表),快速猜測私鑰。例如,在 Profanity 工具的案例中,攻擊者通過分析生成的地址模式,成功破解多個 Ethereum 錢包,竊取大量資金。

  • 建議:使用足夠大的變量類型(如 256 位或更高)存儲隨機數,以支持完整密鑰空間(如 secp256k1 曲線的 2^256 範圍)。

5.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 並檢查其返回值。

0x02 ECDSA 安全

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 密鑰交換時,如果未採取適當的防禦措施,攻擊者可能會成功獲取私鑰信息。

  • 建議:驗證接收的點是否確實位於預期的曲線上。

0x03 EdDSA 安全

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,則拒絕簽名。

0x04 Schnorr 安全

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 簽名相關側信道攻擊事件。

  • 建議:實現恆定時間運算、使用抗側信道的硬體或算法。

0x05 BLS 安全

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) 機制的嚴格驗證,避免依賴簡單求和聚合;考慮使用非線性化聚合或額外隨機性。

0x06 RSA 安全

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) 來驗證消息完整性,防止篡改。

0x07 雜湊安全

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 結構的現代雜湊算法,這些算法天然不受長度擴展攻擊影響。

0x08 AES 安全

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。

0x09 其它密碼學協議

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機制如何守護資金安全