簡體   English   中英

RNGCryptoServiceProvider 不會為相同的 PWD、Salt、Iteration 組合生成相同的 hash

[英]RNGCryptoServiceProvider does not produce same hash for same PWD,Salt,Iteration combination

Oki 所以我想通過在 .Net 中附加隨機鹽來 hash 我的密碼。 我為此目的使用的內置類是RNGCryptoServiceProvider - 生成隨機鹽和Rfc2898DeriveBytes - 到 hash 實際密碼。

但是當我調用 Rfc2898DeriveBytes 的 GetBytes() function 來獲取密碼字符串、SaltBytes 和迭代計數的相同組合時,結果是不同的。 我粘貼我的代碼以供參考

    public class PBKDF2Implementation
    {
        int minSaltSize = 32;
        int maxSaltSize = 64;


        public string CreateHash(string plainText , out string  salt)
        {
            Random random = new Random();
            int saltSize = random.Next(minSaltSize, maxSaltSize);

            // Allocate a byte array, which will hold the salt.
            byte[] saltBytes = new byte[saltSize];

            // Initialize a random number generator.
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
            // Fill the salt with cryptographically strong byte values.
            rng.GetNonZeroBytes(saltBytes);

            string strSalt = System.Text.Encoding.ASCII.GetString(saltBytes);
            //string strSalt = System.Convert.ToBase64String(saltBytes);
            salt = strSalt;

            Console.WriteLine(saltBytes.Count());
            Console.WriteLine(strSalt);

            Rfc2898DeriveBytes pwdGen = new Rfc2898DeriveBytes(plainText, saltBytes, 1000);

            // generate an RC2 key
            byte[] key = pwdGen.GetBytes(32);

            Console.WriteLine(System.Convert.ToBase64String(key));
            return System.Convert.ToBase64String(key);
        }

        public bool CompareHash(string plainText, string salt, string hashValue)
        {

            byte[] saltBytes = System.Text.Encoding.ASCII.GetBytes(salt);
            //byte[] saltBytes = System.Convert.FromBase64String(salt);

            Console.WriteLine(saltBytes.Count());
            Console.WriteLine(System.Text.Encoding.ASCII.GetString(saltBytes));

            Rfc2898DeriveBytes pwdGen = new Rfc2898DeriveBytes(plainText, saltBytes, 1000);

            // generate an RC2 key
            byte[] key = pwdGen.GetBytes(32);

            Console.WriteLine(System.Convert.ToBase64String(key));
            return System.Convert.ToBase64String(key) == hashValue;
        }
    }

在我的測試中 class 我有這個 function

    [Test]
    public void shouldGenerateConsistentHash()
    {
        PBKDF2Implementation cPbkdf2Implementation = new PBKDF2Implementation();
        string salt;
        string hashValue = cPbkdf2Implementation.CreateHash("password", out salt);

        bool result = cPbkdf2Implementation.CompareHash("password", salt, hashValue);
        Assert.IsTrue(result) ;
    }

測試失敗。
但是,如果在上面的 class PBKDF2Implementation 中,如果我將 System.Text.Encoding.ASCII.GetString 行替換為 System.Text.Encoding.Unicode.GetString 並將 System.Text.Encoding.ASCII.GetBytes 替換為 System.Text.Encoding.Unicode。獲取字節

測試通過。 知道為什么會這樣嗎? 我想讓它與 ASCII 編碼一起使用的原因是因為存儲此哈希值的同一數據庫也將被 PHP 應用程序使用 & 只有當鹽編碼是ASCII。

這是相同的 PHP 實現http://www.php.net/manual/en/function.hash-hmac.php#101540

  1. 避免將字符串與加密一起使用。 使用字節arrays,即byte[]
  2. 如果您必須使用字符串,請務必注意編碼。 他們會咬你 10 次中的 9 次;

例如

byte [] data = new byte [] { 65, 0, 65 };
var s = System.Text.Encoding.ASCII.GetString (data);

什么s價值?

答案:“一個”

如果您從同一個字符串中詢問byte[] ,您將得到: byte [1] { 65 } ,它與原始字符串不同,並且不適用於大多數加密用法。

Base64 更安全,因為它會保持每個字節的完整性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM