7

我寫了一個網站,利用SHA-256哈希來驗證用戶的密碼。這是一個相對不安全的設置,因爲大多數用戶將擁有相同的用戶名/密碼。爲了盡力保護它至少一點點,我做了以下內容:Chrome和IE返回不同的SHA哈希值

  1. 客戶端從服務器
  2. 客戶端請求一個新的鹽哈希有這種鹽
  3. 密碼的客戶端發送的散列與鹽回服務器
  4. 服務器密碼哈希實際的密碼,並比較了這兩種

這裏是我的代碼:

C#

//Just for testing! 
private static Dictionary<string, string> users = new Dictionary<string, string>() { { "User", "Password" } }; 

[HttpGet] 
public HttpResponseMessage GetSalt() 
{ 
    RNGCryptoServiceProvider secureRNG = new RNGCryptoServiceProvider(); 
    byte[] saltData = new byte[64]; 

    secureRNG.GetBytes(saltData); 

    HttpResponseMessage response = new HttpResponseMessage(); 
    response.Content = new StringContent(System.Text.Encoding.Unicode.GetString(saltData), System.Text.Encoding.Unicode); 
    return response; 
} 

[HttpGet] 
public bool ValidateUser(string userName, string hashedPassword, string salt) 
{ 
    SHA256Managed hash = new SHA256Managed();   
    if (users.ContainsKey(userName)) 
    { 
     string fullPassword = salt + users[userName]; 
     byte[] correctHash = hash.ComputeHash(System.Text.Encoding.UTF8.GetBytes(fullPassword)); 

     if (hashedPassword.ToUpper() == BitConverter.ToString(correctHash).Replace("-","")) 
     { 
      return true; 
     } 
    } 
    return false; 
} 

的Javascript

$scope.login = function() { 
    $http.get('api/Login').success(function (salt) { 
     //Hash the password with the salt and validate 
     var hashedPassword = sjcl.hash.sha256.hash(salt.toString().concat($scope.password)); 
     var hashString = sjcl.codec.hex.fromBits(hashedPassword); 

     $http.get('api/Login?userName=' + $scope.userName + '&hashedPassword=' + hashString + '&salt=' + salt).success(function (validated) { 
      $scope.loggedIn = validated; 
     }); 
    }); 

此代碼工作正常的谷歌瀏覽器,而不是在Internet Explorer 11(如被看見在調試器)的問題是,哈希由javascript生成的結果與由C#生成的結果不同。

嫌疑人這與字符編碼有關,但在網上沒有發現太多證明/駁斥這個理論(或幫助解決一般問題)。如果有更好的方法來解決這個問題,我很樂意聽到這個消息,但是也想理解原始錯誤的原因。

哈希爲什麼不同,我能做些什麼來解決它?

+0

什麼是「sjcl」?通過基於隨機字符串的大規模比較運行(即,生成一百萬個隨機字符串,在兩側對它們進行散列,比較結果),我會確保JS和C#哈希產生相同的輸出。爲了保持事物的確定性(所以結果很重要),我會在這次測試中不使用鹽。 – Alex

+0

@Alex sjcl是斯坦福大學的Javascript Crypto庫。既然Chrome可以正常工作,你是否建議針對C#運行Chrome瀏覽器,針對C#的IE還是兩者(沒有建議的鹽)? – BradleyDotNET

+0

以上所有內容:如果Chrome始終可用,IE永遠不會,那麼您可以確認它是瀏覽器問題。現在,如果其中一個*有時*可以工作... – Alex

回答

3

IE確實是而不是就像查詢字符串中的Unicode字符一樣。它也不喜歡ASCII的一些「特殊」字符。即使它正確地接受它們,並正確執行散列,但在運行此代碼時,salt是「???????」來自IE瀏覽器時,以及來自Chrome的正確字符串。

簡單的解決方法是將salt的字符集限制爲大寫,小寫和數字。使用這種方法,兩個瀏覽器都給出了正確的散列。