如何安全且隨機地迭代從 Scrypt 派生的密鑰?
我正在開發一種基於某些使用者輸入(腦錢包)確定性地為任意橢圓曲線生成私鑰的方法。目前,我正在使用具有強大難度參數的 Scrypt 密碼散列算法將多個輸入參數散列到一個密鑰中。
Scrypt 的輸出應該均勻分佈在 $ [0, 2^{b}) $ 在哪裡 $ {b} $ 是從 Scrypt 算法輸出中使用的輸出位數。但是有效的橢圓曲線私鑰必須小於曲線的有限域階 $ N $ , 均勻分佈在 $ [0, N) $ . 因此,直接使用 Scrypt 的輸出作為私鑰 mod $ N $ 會在生成的結果密鑰中產生一個小的偏差 - 壞消息,所以我需要避免這種情況。
通常,如果您使用安全的 RNG 生成私鑰,您只需重試 RNG,直到獲得的數字小於 $ N $ ,您可以安全地將其用作私鑰。
有沒有一種安全的方法來確定性地迭代 Scrypt 的輸出,這樣我們就可以保留 Scrypt 輸出的偽隨機分佈,而無需使用新參數重新執行 Scrypt?
我考慮的一種方法是使用 SHA256 或 SHA512 對 scrypt 的輸出進行雜湊處理,直到小於 $ N $ ,但這對於大於 512 位的曲線(例如 P521)效果不佳。
另一個不太優雅的解決方案是簡單地拒絕任何產生大於的密鑰的輸入參數 $ N $ . 它應該很少發生,所以也許我可以僥倖逃脫?有沒有常見的曲線,其順序 $ N $ 是不是它的第二高冪的很大一部分?
因此,直接使用 Scrypt 的輸出作為私鑰 $ \bmod N $ 會在生成的結果密鑰中產生一個小的偏差 - 壞消息,所以我需要避免這種情況。
實際上,偏差不會大到可以利用。但是假設你想完全避免這種情況……
有沒有一種安全的方法來確定性地迭代 Scrypt 的輸出,這樣我們就可以保留 Scrypt 輸出的偽隨機分佈,而無需使用新參數重新執行 Scrypt?
兩種明顯的方法:
- 讓 Scrypt 生成(比如說) $ log_2 N + 128 $ 位,並評估 $ \bmod N $ ; 由此產生的偏差將非常小,無法測量,更難以利用
- 將 Scrypt 的輸出傳遞給SHAKE;然後擠出來 $ \lceil log_2 N \rceil $ 位(如果它使實現更簡單,可能是偶數字節),並且它返回的值恰好大於 $ N $ ,擠出更多的位。
第二個類似於您使用 SHA256 或 SHA512 的想法;然而,因為 SHAKE 允許我們擠出任意多的位,我們可以輕鬆地擴展它來處理 P521。
哦,既然你問了:
有沒有常見的曲線,其順序 $ N $ 是不是它的第二高冪的很大一部分?
好吧,我想到了Brainpool曲線——我不知道它們的使用非常普遍。但是我確實相信它們有時會被使用。