具有快速加密的基於密碼的密碼
將基於密碼的密碼定義為解密密鑰是人類容易記住的密碼的密碼,因此樂觀地說最多有 28 到 44 位熵(根據強制性 XKCD)。
對於具有任何實際安全性的基於密碼的密碼,解密肯定會很慢(並且隨著技術進步使密碼搜尋更快,加密調整以保持解密緩慢)。執行此操作的傳統方法是使用適當參數化的熵拉伸基於密碼的密鑰派生函式(例如PBKDF2、bcrypt、scrypt或Argon2)將密碼(可能還有隨機salt)轉換為普通密碼的密鑰. 加密和解密都是這樣做的,這使得兩者都一樣慢。
什麼是可推薦的(最好是通用的或/和標準化的)基於密碼的快速加密密碼?
一種選擇是 $ (\text{password},\text{plaintext})\mapsto\text{ciphertext} $ 那很快,而 $ (\text{password},\text{ciphertext})\mapsto\text{plaintext} $ 仍然與傳統的基於密碼的密碼一樣困難,以獲得可比的安全級別。還有其他選擇,我不想太直接,看看會出現什麼好的想法。
您可能會考慮的一種方法是拼圖;這是解密器必須進行一些搜尋才能找到結果的地方。
這是一個簡單的例子:假設加密器獲取密碼,並選擇 $ N $ 隨機位;他將兩者連接起來,然後 SHA-256 對結果進行雜湊處理。然後,他取出散列的前 128 位,將其放入密文中,然後使用其他 128 位對秘密進行 AES 加密;這就是密文的其餘部分。
然後他丟棄了原來的 $ N $ 他選擇的位。
要解密這個,我們必須搜尋 $ N $ 選擇的隨機位;為此,我們必須計算平均值 $ 2^{N-1} $ 雜湊,這是相當慢的。一旦我們選擇了正確的隨機位集合,就很容易辨識它(通過將該散列與密文中散列的初始部分進行比較);然後我們可以解密消息。
你可以選擇 $ N $ 去嚐嚐; 如果你想解密可能需要一秒鐘,也許是 24;如果你想讓它更貴,也許是 32。
您可以對這種方法進行一些調整:
- 使用多個級別的謎題,以減少可能快速完成解密的機會(通過早期偶然發現答案)
- 使用除 SHA-256 以外的東西(它對 GPU 相當友好)。
但是,我不明白如何使這種方法能夠抵抗大型多 CPU 攻擊……
如果最小化解密時間的變化很重要,一個想法是並行而不是串列排列謎題。也就是說,我們選擇 $ k $ 不同的隨機值 $ n $ 每個位,併計算 $ k $ 價值觀:
$$ h_i = \text{Hash}( \text{Password} || r_i ) $$ 並暴露 $ z $ 每個位(對於某些 $ z $ 略大於 $ n $ ).
然後,我們計算最終的雜湊 $ \text{Hash}( h_0, h_1, …, h_{k-1} $ ,公開其中的 128 位(並使用其他 128 位作為實際密鑰)。
要解密,需要有人計算 $ \text{Hash}( \text{Password} || x ) $ 對於不同的值 $ x $ ,並查看是否匹配任何部分顯示的 $ h_i $ 價值觀。解密器將需要所有 $ k $ 其中,因此需要嘗試幾乎所有 $ 2^n $ 的可能值 $ x $ .
例如,對於 $ \text{Hash} = \text{SHA-256} $ , $ n = 28 $ (我的測試機器的單個for可以執行 $ 2^{28} $ 每分鐘 SHA-256 雜湊值), $ z=32 $ 和 $ k = 10 $ ,那麼這將產生大約 10% 變化的解密,具有 56 字節的成本……
我為我的問題描述了一個枯燥的解決方案,以便其他人不必:使用非對稱混合加密(例如curve25519xsalsa20poly1305),從最先進的基於密碼的密鑰的輸出中生成私鑰導函式,例如Argon2。
用於加密的公鑰從密碼中獲取一次,然後儲存;這不是秘密。因此,通過訪問受信任的公鑰,加密速度很快,或者對於知道密碼、進行多次加密並且具有受信任完整性的儲存的人來說,平均速度很快,可以在其上寫入一次公鑰。解密需要密碼(不儲存私鑰),或者通過暴力破解。
與poncho 的回答中提出的對稱謎題的使用相比,該建議具有嚴重的實際缺點,即第一次加密與解密一樣慢。它的一個小優點是解密時間非常均勻,不會產生我無法避免的密文大小成本,這是我在多個級別的謎題中無法通過謎題方法推測性獲得的。
注意:我遠不排除還有其他技術。