Key-Derivation

PasswordDeriveBytes 背後的算法是什麼?

  • October 10, 2016

PasswordDeriveBytesMicrosoft 在該類中創建了 PBKDF1 的實現。但是,它可以生成比 PBKDF1 更多的字節,而 PBKDF1 受限於底層雜湊函式生成的字節數。微軟的這個專有擴展是如何定義的?

Microsoft 實現中的密碼P首先使用 UTF-8 進行編碼。迭代次數c預設為100,雜湊算法HashSHA-1。

輸出與 PBKDF1 相同,最大輸出大小為 PBKDF1,即散列的輸出大小。之後,倒數第一個散列以計數器為前綴(作為包含使用 ASCII 編碼的十進制數字的字元串)並再次散列以產生輸出。如果GetBytes被多次呼叫,它只會從流中返回下一個輸出字節。

請注意,此描述並未描述 Microsoft 與早期 Windows 作業系統一起提供的損壞的實現。那些包含一個錯誤GetBytes,如果它被呼叫兩次或更多次,可能會導致方法的輸出重複。

下面是對該算法的更正式的描述。它擴展了 RFC 2898 第 5.1 節中 PBKDF1 的定義

PBKDF1_MS (P, S, c, dkLen)

  Options:        Hash       underlying hash function

  Input:          P          password, an octet string
                  S          salt, an eight-octet string
                  c          iteration count, a positive integer
                  dkLen      intended length in octets of derived key,
                             a positive integer, bounded to 100 times
                             the output size of Hash

  Output:         DK         derived key, a dkLen-octet string

  Steps:

     1. If dkLen > 100 * Hash output
        "derived key too long" and stop.

     2. Apply the underlying hash function Hash for c iterations to the
        concatenation of the password P and the salt S,
        apply the Microsoft extension by hashing the concatenation of
        an encoded counter and the output of the hash produced for
        iteration c - 1, then extract the first dkLen octets to produce
        a derived key DK:

                  T_1 = Hash (P || S) ,
                  T_2 = Hash (T_1) ,
                  ...
                  T_c = Hash (T_{c-1}) ,
                  R_1 = T_c ,
                  R_2 = Hash (Ctr(1) || T_{c-1}) ,
                  ...
                  R_n = Hash (Ctr(n-1) || T_{c-1}) ,
                  R = R_1 || R_2 || ... || R_n
                  DK = R<0..dkLen-1>

     3. Output the derived key DK.

   The Ctr function converts the given number to a decimal
   representation in ASCII.

C# 中的原始 Mono 實現在這裡。Java 埠在這裡


強烈建議您使用RFC2898DeriveBytes實現 PBKDF2 的替代。

如果 PBKDF2 的輸出需要超出底層雜湊的輸出大小,則建議使用基於密鑰的密鑰派生函式,例如 HKDF。如果您沒有實現,那麼只需對輸出和靜態大小的標識符進行雜湊處理,以創建派生鍵SHA-256(master | identifier)並根據需要從左側獲取盡可能多的字節。

引用自:https://crypto.stackexchange.com/questions/22271