使用不同的 IV 和 SALT 和 AES-CBC 但相同的 KEY
我正在做這個項目,客戶可以發送消息,現在顯然用純文字發送它不是很聰明。所以我決定用 AES-CBC 加密它。
現在,每次我加密某些東西時,KEY 都是使用RFC-2829中定義的 PBKDF2 派生的,如下所示:
DERIVED = PBKDF2(鹽:16 個隨機字節,密鑰:明文密碼,迭代計數= 16834)
這就是關鍵。IV 每次都不同,但它包含在最終的密文中。
問題:使用 DERIVED 密鑰是否安全,其中 ORIGINAL 密鑰是相同的,但鹽每次都不同?
問題:使用 DERIVED 密鑰是否安全,其中 ORIGINAL 密鑰是相同的,但鹽每次都不同?
不,但原因有點棘手。
首先,忘記 AES-CBC——您應該使用經過身份驗證的密碼,例如 AES-GCM(如果您必須使用 AES)或 NaCl crypto_secretbox_xsalsa20poly1305,並專注於安全合約。AES-CBC 很難正確使用,即使您這樣做也不能提供良好的安全性。如果您真的只需要使用已協商的單個密鑰按順序發送多條消息,則可以將迄今為止發送的消息數量用作經過身份驗證的密碼的隨機數——無需派生密鑰。
其次,如果使用者選擇他們自己的密碼,你應該使用像 Argon2(特別是 Argon2id)這樣的現代密碼雜湊,而不是 PBKDF2,這樣你就可以利用更多的使用者資源來提高對手的成本——特別是,所以您也可以利用使用者的記憶體和並行性。(如果使用者沒有選擇他們自己的密碼——如果電腦選擇的是(比如說)256 位熵的密碼——那麼就不需要密碼散列,你可以跳過這一步。)
但是假設您出於某種原因必須使用 PBKDF2,所以這是提高對手成本的唯一方法。您是否應該反複使用帶有多個鹽的 PBKDF2 來派生多個密鑰?
迭代計數的目的是提高對手的成本,但同時也會提高合法使用者的成本。但是成本對合法使用者和對手來說意味著一些不同的東西:
- 合法使用者關心密鑰派生的延遲****:**在我輸入密碼並提示 ENTER 後,我必須等待多長時間才能登錄?
如果我願意等待(比如說)一秒鐘,那麼應用程序可以在 PBKDF2 上花費一秒鐘的資源來提高對手的成本。 從使用者的角度來看,在一秒鐘內計算一個鍵**與在半秒內連續計算兩個鍵沒有區別。但從對手的角度來看,情況有所不同。
- 對手關心密碼猜測的吞吐量**:在我的 100-CPU 集群上,他們每小時能猜出多少個密碼?
攻擊者並不關心在密碼搜尋過程中獲取應用程序所需的每個密鑰。如果對手在應用程序中使用一個密鑰來確認密碼猜測,他們會很高興。 如果應用程序必須在一秒鐘內為兩個不同的密鑰計算兩次 PBKDF2,那麼攻擊者只需要花半秒鐘的時間來測試密碼猜測。
更糟糕的是,如果您向 PBKDF2 詢問一個比散列輸出大小更長的鍵,就**好像您以相同的迭代次數連續多次呼叫 PBKDF2。在某些應用程序中這可能不會受到傷害,但這在很大程度上是一個愚蠢的設計。
那麼你應該如何從一個密碼中派生多個密鑰呢?
假設您不能只重用具有不同隨機數的密鑰。
答:使用密鑰派生函式,例如帶有 SHA-256 的 HKDF。 (不是基於密碼的密鑰派生函式,也稱為密碼雜湊——只是一個普通的密鑰派生函式;更多關於區別。)密鑰派生函式需要一個主密鑰,例如您從 PBKDF2 獲得的密鑰,以及一個唯一的字元串辨識有時稱為“資訊”的目的,並返回派生的子鍵。每次輸入相同的主密鑰和資訊時,都會返回相同的子密鑰,但在不知道主密鑰的情況下,子密鑰似乎是獨立的統一隨機位串。
例如,您可以這樣做:
- 主密鑰: $ k = \operatorname{PBKDF2-HMAC-SHA256}(\mathit{salt}, 16384, \mathit{pw}) $
- 文件加密密鑰: $ k_f = \operatorname{HKDF-Expand}_k(\text{‘file encryption’}) $ .
- 備份加密密鑰: $ k_b = \operatorname{HKDF-Expand}_k(\text{‘backup encryption key’}) $ .
- 等等
(注意:HKDF 有兩個步驟——HKDF-Extract 和 HKDF-Expand。HKDF-Extract 在這裡不是必需的:它的目的是將高熵但不均勻的位串,如 diceware 密碼,映射成一個短的均勻位串,但是 PBKDF2 已經為我們做到了。HKDF-Expand 採用一個短的統一位字元串和一個資訊參數,並派生一個子密鑰。如果您只有一個組合的 HKDF-Extract/Expand 模組可供您使用,那麼這樣做也沒有什麼壞處HKDF-Extract 在 PBKDF2 的輸出上,但它也沒有做任何有用的事情。)
附錄:鹽呢?
salt的目的是減輕多目標攻擊:如果每個人都使用相同的salt,那麼打破第一個 $ t $ 目標會比打破一個目標便宜一倍 $ t $ ,因為對手可以通過一次批量攻擊多個目標來節省精力。對手喜歡這樣的批量優勢,因為一旦您踏入網路大門,您通常可以利用它來破壞更多網路。但是,如果每個人都使用不同的鹽,那麼 $ t $ 批量優勢消失。
對於密鑰派生,使用 PBKDF2、Bcrypt、Scrypt,或者更好地使用Argon2id。Argon 是密碼雜湊競賽的獲勝者
問題:使用 DERIVED 密鑰是否安全,其中 ORIGINAL 密鑰是相同的,但鹽每次都不同?
如果你使用不同的隨機生成的鹽,你會沒事的。您還可以將計數器附加到每個密鑰生成的密碼。請記住,密碼必須足夠強大以抵禦字典攻擊。無密鑰派生可防止您選擇錯誤的密碼。
不要使用CBC模式。這是一種古老的操作模式,並且存在問題,例如,IV 必須是不可預測的,並且您可能會遇到位翻轉攻擊。padding oracle 攻擊可能與您的情況無關。
在現代密碼學中,我們使用AES-GCM 或 ChaCha20-Poly1305 等認證加密(AE) 模式。使用 AE,您不僅會獲得機密性,還會獲得完整性和身份驗證。
您也沒有考慮如何發送密鑰或密鑰協議。您可以使用 Ephemeral DHKE、RSA-KEM,它需要公鑰並且可能難以正確實施。您可以使用現有的庫,例如使用公鑰加密的Crypto_box 。您可能還對Signal Protocole感興趣。