2017-01-05 71 views
2

我一直在閱讀有關數據庫(https://crackstation.net/hashing-security.htm)確保用戶的密碼。基本的想法是理解的 - 生成一個隨機的Salt,將其附加到密碼並散列密碼。保護用戶的密碼 - Rfc2898DeriveBytes VS SHA512

所以這裏就是我所做的(我沒有把這裏一些方法做轉換爲字符串):

RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create(); 
byte[] rndBytes = new byte[512]; 
randomNumberGenerator.GetBytes(rndBytes); 
string salt = ToHexString(rndBytes); 

var sha512Hasher = SHA512.Create(); 
string hashedPwd = ToHexString(sha512Hasher.ComputeHash(GetBytes(pwd + salt))) 

根據這篇文章,這是保證,但可以更使用安全「鍵伸縮「這對我的理解是哈希做得比較慢(使用參數)使密碼變得更難。

因此,這裏是我所做的:

RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create(); 
byte[] salt = new byte[512]; 
randomNumberGenerator.GetBytes(salt); 
Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes(user.Password, salt, 1000); 
byte[] hashBytes = k1.GetBytes(512); 
string hash = ToHexString(hashBytes); 

現在,這裏是我的問題:

  1. 是什麼SHA512Rfc2898DeriveBytes之間的區別?哪個更安全?
  2. 我應該用更少的鹽和更多的迭代?它會使它更安全嗎?
  3. 在它運行速度非常快1000次迭代 - 多慢應該是什麼?半秒鐘?一秒?這裏的經驗法則是什麼?
  4. 在數據庫 - 我應該字節數組轉換爲字符串和存儲字符串或者我應該存儲在一個二進制數據字段中的字節數組?

編輯(另一個問題)

  • 如果我遍歷換湯不換藥SHA512 1000次 - 它給予同樣的安全性?
  • 回答

    4
    1. SHA512和Rfc2898DeriveBytes有什麼區別?

    SHA512是一個密碼散列函數,而Rfc2898DeriveBytes是一個密鑰派生函數。正如你已經寫過的那樣,散列函數太快而且可能很容易被暴力破壞,這就是爲什麼我們需要像BCrypt,SCrypt,PBKDF2或Argon2這樣的成本因子的函數。據我所知,Rfc2898DeriveBytes使用帶SHA1的HMAC來實現PBKDF2。這回答您的其他問題,一個迭代SHA比Rfc2898DeriveBytes 安全。

  • 我應該有更多的迭代較小鹽?
  • 鹽和成本因素並不相關,並有不同的目的。鹽防止彩虹桌的使用,迭代是對暴力攻擊的反措施。您可以從我的tutorial獲取有關安全密碼存儲的更多信息。所以不,不要讓鹽變短。

    1. 它應該有多慢?

    當然這取決於您的服務器和您的安全要求,速度較慢意味着難以蠻力。一個經驗法則是關於單個散列的大約50 milliseconds

    1. 關於數據庫 - 我應該將字節數組轉換爲字符串嗎?

    這取決於你。字符串更容易處理備份,遷移和調試,而字節數組需要更少的數據庫空間。也許你還應該看看BCrypt.Net,它生成的字符串作爲包含salt的輸出,並且很容易存儲在單個數據庫字段[string]中。

    +0

    那麼根據你所說的第二個例子 - 使用Rfc2898DeriveBytes生成鹽和迭代比第一個例子更安全嗎? – developer82

    +0

    @ developer82 - 正確,存儲密碼更安全。 – martinstoeckli

    +0

    我會在這裏添加一個關於大於底層散列函數的密鑰延伸的評論。 OP的PBKDF2代碼的長度爲** 1KB **,遠遠大於它應該得到的結果。 –