Security

比特幣鏈中籤名中不安全的 64 位隨機數的起源是什麼?

  • January 11, 2019

Biased Nonce Sense: Lattice Attacks against Weak ECDSA Signatures in Cryptocurrencies Joachim Breitner 和 Nadia Heninger 使用基於格的算法從比特幣鏈中的簽名中恢復私鑰,這些簽名是由不安全的簽名者生成的,這些簽名產生了有偏見的 nonce。

他們發現的一大類不安全簽名是 2014 年 7 月 26 日至 2015 年 6 月 1 日期間的 5,863 個簽名,這些簽名用於隨機數大小僅為 64 位的多重簽名腳本中。在論文中,當多次使用單個密鑰來簽署多個消息(可能是單個事務中的多個輸入)時,隨機數之間的差異很小,他們的算法能夠確定實際使用的隨機數和具有高機率的私鑰.

在多個簽名中使用一個小的 nonce 只是一個特別簡單的具有小差異的情況。小隨機數也可以用更簡單的蠻力搜尋方法攻擊,而不需要多個簽名,但該論文的方法比蠻力快得多。他們的方法還能夠攻擊使用的許多 110 - 160 位隨機數,這個範圍會使蠻力搜尋不太現實。

作者不知道 64 位隨機數的來源,但“假設這可能是用於多因素安全性的錯誤實現,例如硬體令牌”。

我們對這些簽名的實際來源了解多少?

根據時間框架和我對在那段時間開發錢包軟體的各個團體的能力的印象,我最初的猜測是 Bitpay 共付額軟體可能是這些簽名的來源。Copay 是一個多重簽名錢包,最初是在那個時候發布的。

由於我不是 javascript 開發人員,因此我花了一些精力來探勘歷史依賴項以找到當時適用的程式碼,但我相信我的懷疑很可能得到證實

[如果有一些工具可以在某個日期獲取 JS 應用程序的所有依賴項,這將非常有用。]

return new bignum(SecureRandom.getRandomBuffer(8));

此程式碼選擇一個 8 字節(64 位)隨機數。我不清楚這個錯誤究竟是如何發生的——例如,將 32 發送到一個將比特作為大小參數的函式是有道理的——但它發生了它並沒有被審查並且似乎已發貨。

引入該漏洞的拉取請求是通過將底層 EC 操作切換到不同的庫“橢圓”來加快 javascript 加密實現的速度。當時,橢圓具有自己的簽名功能,其中包括 RFC6979 確定性隨機數生成。我不明白為什麼即使在支持 PR 的橢圓評論的作者的情況下,bitcore 也沒有更改為使用橢圓簽名功能,但由於存在預先存在的“家庭滾動”簽名程式碼,任何人都可能沒有想到切換到庫常式。關於拉取請求的討論不多。

該漏洞隨後得到修復,但弱簽名繼續創建了一段時間。因為 Bitpay 的 bitcore 被宣傳為一個通用的比特幣庫,所以除了 copay 之外的其他軟體可能已經採用了它。

除了儲存庫中的修復程序之外,我找不到任何關於此漏洞的公告或討論。

雖然我沒有仔細分析它,但我注意到在切換到橢圓之前,程式碼庫以前使用過“bitcoin-js”——至少在某些版本中——使用了一個隨機數生成器,該生成器由於逃避審查而很弱細微的類型錯誤,因此很可能是引入錯誤的更改只是將軟體從一種形式的弱點更改為另一種形式的弱點。

也有可能,儘管 bitcore 在正確的時間引入了完全正確的漏洞,但它是巧合的,並且在論文中發現的錯誤簽名是由其他一些實現創建的。如果是這樣,我認為平行斷裂仍然是有益的。

我認為研究和相關程式碼是一個很好的例子,說明這些事情是多麼容易出錯,即使是很小的錯誤也可能導致完全的安全漏洞,並且僅僅因為某些東西是開源的事實並不能自動確保它得到了充分的審查。

引用自:https://bitcoin.stackexchange.com/questions/83559