2013-06-19 152 views
5

有誰知道從任何長度的密碼短語中生成256位密鑰值的方法嗎?由於需要再次生成加密值並在數據庫中進行比較,因此不能加密加密。所以每次加密時必須生成一個相同的加密字符串。生成AES 256位密鑰值

目前我正在使用一個32位字符密鑰工作在可能不正確的假設這是256位?

所以,我想'快速棕色狐狸'被轉換爲合適的AES 256位密鑰?

+2

「加密不能被加密,因爲需要再次生成加密值」這就是爲什麼通常將salt與散列密碼一起存儲。這樣,如果兩個不同的用戶具有相同的密碼,它會生成不同的哈希值,但對於單個用戶,相同的密碼將始終生成相同的哈希值。 – svick

+0

坦率地說,沒有鹽它沒有真正加密。不應該可以對加密值進行直接數據庫查找。 – Matthew

回答

12

可以構建Rfc2898DeriveBytes Class具有任意大小的密碼,然後派生所需大小的關鍵在這種情況下,256個比特(32個字節):

private static byte[] CreateKey(string password, int keyBytes = 32) 
{ 
    const int Iterations = 300; 
    var keyGenerator = new Rfc2898DeriveBytes(password, Salt, Iterations); 
    return keyGenerator.GetBytes(keyBytes); 
} 

爲了產生確定性的輸出(即相同的輸入將產生相同的輸出),您將需要對鹽進行硬編碼。該鹽必須至少爲8個字節:

private static readonly byte[] Salt = 
    new byte[] { 10, 20, 30 , 40, 50, 60, 70, 80}; 
+0

請參閱我對上述更多理論描述的解釋。請注意''Rfc2898DeriveBytes'實現PBKDF2 :) –

+0

謝謝 - 這是非常有用的。如果keySize是32,但獲得一個32字節的鍵陣列? – bhs

+0

是的,我想這是ByteBlast的一個錯誤。我還建議你使用UTF-8編碼將密碼編碼爲字節,因爲Rfc2898DeriveBytes函數沒有明確指定它使用的編碼。當你使用另一個運行時的函數時,這很棘手。 –

-1

您可以使用一些散列函數,它提供來自任何長度輸入的256位輸出,例如SHA256。

+1

官方散列不是一個基於密碼的密鑰派生函數,不應該直接用於這種情況。 –

2

也許最好的方法是使用PBKDF2使用SHA256(其將產生256位的輸出)和一個特殊應用鹽&迭代計數。您應該知道,使用特定於應用的鹽會從PBKDF2中移除相當多的保護,因此您可能需要額外的保護來緩解此問題。一種方法是確保數據庫安全,並且可以使用最大嘗試次數。

您在規定32字符密碼不是256位密鑰時是正確的。它不包含足夠的熵,有些字節可能甚至沒有有效的字符表示。

+0

請參閱ByteBlasts答案以上的實現:) –

+0

感謝 - 所以上述方法的32字節數組是256位密鑰? – bhs

+0

這是一個基於密碼的密鑰派生函數,這就是PBKDF的含義。你輸入一個密碼,你得到一個密鑰(作爲字節)。它具有使用鹽和多次迭代的保護,這使得計算密鑰相對困難(對於您和攻擊者而言)。攻擊者可能需要做很多事情才能獲得關鍵。但是,最好使用SHA-256或更高版本,因爲它需要對超出一個散列輸出的任何內容執行全部迭代次數 - 這可能只會影響到您而不是攻擊者。 –