我写了一个利用SHA-256哈希来验证用户密码的网站.这是一个相对不安全的设置,因为大多数用户将拥有相同的用户名/密码.为了尝试保护它至少一点点,我做以下事情:
>客户端从服务器请求新的salt
>客户端使用此盐哈希密码
>客户端将带有salt的哈希密码发送回服务器
>服务器哈希实际密码并比较两者
这是我的代码:
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; }); });
此代码在Google Chrome上运行良好,但在Internet Explorer 11上运行不正常.问题(如调试器中所示)是javascript生成的哈希值与C#生成的哈希值不同.
我怀疑这与字符编码有关,但在网上没有发现很多东西来证明/反驳这个理论(或者总体上帮助解决这个问题).如果有更好的方法来解决这个问题,我很高兴听到它,但也希望了解原始错误的原因.
为什么哈希不同,我该怎么做才能解决它?