2016-03-05 16 views
0

我對下一個(簡化的)代碼片斷感到困惑。當用戶註冊它加密密碼時,將散列轉換爲字符串並將其保存在數據庫中。在用戶嘗試登錄後,代碼從db讀取密碼,獲取它的字節,並與用戶輸入的密碼的加密哈希進行比較。源字節數組到字符串,然後回到字節數組與源不同

static void Main(string[] args) 
{ 
    //User registration 
    byte[] passwordBytes = Encoding.Unicode.GetBytes("[email protected]"); 
    byte[] hashBytes = GetHash(passwordBytes); 
    string stringFieldInDb = Encoding.Unicode.GetString(hashBytes); //password hash is being stored in database 


    //Check password 
    byte[] hashBytesInDb = Encoding.Unicode.GetBytes(stringFieldInDb); //was read from database 

    byte[] enteredPasswordBytes = Encoding.Unicode.GetBytes("[email protected]"); 
    byte[] enteredPasswordHash = GetHash(enteredPasswordBytes); 

    //is false 
    var isPasswordValid = hashBytesInDb.SequenceEqual(enteredPasswordHash); 

    //this way is true 
    var isPasswordValid2 = stringFieldInDb == Encoding.Unicode.GetString(enteredPasswordHash); 
} 

private static byte[] GetHash(byte[] data) 
{ 
    return new SHA512CryptoServiceProvider().ComputeHash(data); 
} 

哈希是有點不同,從數據庫散列串的字節數:

中登錄從輸入的密碼產生的散列串的
161, 127, 0, 49, 27, 146, **253, 255**, 109, 214, **253, 255**, 113, 75, 226, ... 

字節:

161, 127, 0, 49, 27, 146, **74, 219**, 109, 214, **65, 220**, 113, 75, 226, ... 

予縮短上面的例子到三條線,我想知道結果的原因是什麼?

byte[] someCharBytes = new byte[] { 74, 219 }; 
string someChar = Encoding.Unicode.GetString(someCharBytes); 
byte[] differentSomeCharBytes = Encoding.Unicode.GetBytes(someChar); //returns { 253, 255 } 
+0

作爲一個側面說明,不要忘記鹽你的密碼。事實上,使用內置的'Rfc2898DeriveBytes'類來散列密碼更好。檢查了這一點:http://stackoverflow.com/a/10402129/227267 –

回答

4

你正在做的是試圖將散列數據(本質上是隨機字節)解釋爲有效的UTF-16數據。這是行不通的。並非所有字節組合都是有效的。您所獲得的特定字節253, 255U+FFFD REPLACEMENT CHARACTER的UTF-16表示,它是用於通知無效字節序列的字符。

如果您需要將字節數組轉換爲字符串進行存儲, base64編碼非常流行。請查看Convert.ToBase64StringConvert.FromBase64String

+0

感謝您的明確答案 –