Chrome和IE返回不同的SHA哈希值

Bra*_*NET 7 javascript c# internet-explorer google-chrome asp.net-web-api2

我写了一个利用SHA-256哈希验证用户密码的网站.这是一个相对不安全的设置,因为大多数用户将拥有相同的用户名/密码.为了尝试保护它至少一点点,我做以下事情:

  1. 客户端从服务器请求新的salt
  2. 客户端用这个盐哈希密码
  3. 客户端将带有salt的哈希密码发送回服务器
  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;
}
Run Code Online (Sandbox Code Playgroud)

使用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;
        });
    });
Run Code Online (Sandbox Code Playgroud)

此代码在Google Chrome上运行良好,但在Internet Explorer 11上运行不正常.问题(如调试器中所示)是javascript生成的哈希值与C#生成的哈希值不同.

怀疑这与字符编码有关,但是在网上没有发现很多东西来证明/反驳这个理论(或者总体上帮助解决这个问题).如果有更好的方法来解决这个问题,我很高兴听到它,但也希望了解原始错误的原因.

为什么哈希不同,我该怎么做才能解决它?

Bra*_*NET 3

IE 不喜欢查询字符串中的 Unicode 字符。它也不喜欢一些 ASCII 的“特殊”字符。即使它正确地接受它们,并正确地执行哈希,当您运行此代码时,盐是“???????” 来自 IE 时为正确的字符串,来自 Chrome 时为正确的字符串。

简单的修复方法是将 salt 的字符集限制为大写、小写和数字。使用此方法,两个浏览器都会给出正确的哈希值。