验证散列密码不起作用 [英] Verification of Hashing password is not working
问题描述
我提出了一个问题,那就是我得到了很多很好的反馈,并提供了一个很好的答案。我认为我对2次哈希值的验证检查做错了。也许在循环中的代码是好的,但我的代码与理解字节和base64等是问题?
这是原始问题。
密码散列 - 为什么使用盐60,000次
问题是这些哈希不匹配 if(resultHash.Equals(hashPassword))
代码
public string BuildVerify()
{
string password =;
string salt =;
byte []结果;
使用(var sha256 = SHA256.Create())
{
password =hovercraft;
//步骤1:您可以使用RNGCryptoServiceProvider来获得值得使用
的密码var passwordHashing = new PasswordHashing();
salt = passwordHashing.CreateRandomSalt();
//步骤2
字符串哈希=
Convert.ToBase64String(sha256.ComputeHash(Encoding.UTF8.GetBytes(salt + password)));
//步骤3
result = sha256.ComputeHash(Encoding.UTF8.GetBytes(salt + hash));
//步骤4
(int i = 0; i <60000; i ++)
{
结果=
sha256.ComputeHash(编码.UTF8.GetBytes(salt + Convert.ToBase64String(result)));
}
}
// TESTING VERIFY this works ..
字符串SaltAndPwd = string.Concat(password,salt);
SHA256 sha2 = SHA256Managed.Create();
byte [] buff = sha2.ComputeHash(Encoding.Unicode.GetBytes(SaltAndPwd));
string resultHash = Convert.ToBase64String(buff);
string hashPassword = Convert.ToBase64String(result);
if(resultHash.Equals(hashPassword))
{
// perfect
}
return;
$ b public class PasswordHashing
{
public string CreateRandomSalt()
{
string password =;
password = HashPassword.CreateSalt(8)+=;
password = password.Replace(/,c);
返回密码;
$ b public static string CreateSalt(int size)
{
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte [] buff = new byte [size];
rng.GetBytes(buff);
return Convert.ToBase64String(buff);
}
更新 - 问题
好的,我使用了答案中的代码,但显然我的假设是不正确的,因为我无法使用我的代码来验证
//这应该存储在数据库中,例如哈希结果
var newsalt = SOPasswordHasher.GetSalt();
//我们计算散列,然后存储结果。下一次你想认证某人
//你必须重新使用相同的盐并重新计算散列,然后比较
//存储的散列与新的散列
var result = Convert。 ToBase64String(SOPasswordHasher.Hash(hovercraft,newsalt));
字符串SaltAndPwd = string.Concat(hovercraft,newsalt);
SHA256 sha2 = SHA256Managed.Create();
byte [] buff = sha2.ComputeHash(Encoding.Unicode.GetBytes(SaltAndPwd));
string resultHash = Convert.ToBase64String(buff);
if(result.Equals(resultHash))
{
// perfect
}
这里有一个可重用的类,您可以使用它(更少依赖转换为base64):
class SOPasswordHasher
{
///< summary>
///密码哈希
///< / summary>
///< param name =password>您要散列的密码< / param>
///< param name =salt>(crypto-secure)随机值的字节数组< / param>
///< param name =iterations>迭代次数。默认值是60,000< / param>
///<返回>包含散列密码的字节数组< /返回>
$ b $ public static byte [] hash(string password,byte [] salt,int iterations = 60000)
{
using(var sha256 = SHA256.Create())
{
byte [] passwordBytes = Encoding.UTF8.GetBytes(password);
//步骤2
byte [] hash = sha256.ComputeHash(passwordBytes.Concat(salt).ToArray());
//步骤3
byte [] result = sha256.ComputeHash(salt.Concat(hash).ToArray());
//步骤4
for(int i = 0; i {
result =
sha256.ComputeHash(salt .Concat(结果).ToArray());
}
返回结果;
$ b $ public static byte [] GetSalt(int size = 32)
{
byte [] salt = new byte [size];
using(var cryptoServiceProvider = new RNGCryptoServiceProvider())
{
cryptoServiceProvider.GetBytes(salt);
}
返回盐;
$ / code $ / pre
以下是一个用法示例:$ / $>
//这应该存储在数据库中,例如哈希结果
var salt = SOPasswordHasher.GetSalt();
//我们计算散列,然后存储结果。下一次你想认证某人
//你必须重新使用相同的盐并重新计算散列,然后比较
//存储的散列与新的散列
var result = Convert。 ToBase64String(SOPasswordHasher.Hash(hovercraft,salt));
重要提示:我不保证此代码可安全使用,因为我是不是安全专家。布鲁斯·施奈尔说得最好:业余爱好者制作业余密码学
I have asked a question of which I did get a lot of great feedback, along with a good answer. I assume that I am doing something wrong with my verification check of the 2 hashes. Perhaps the code in the loop is fine, but my code with understanding of bytes and base64 etc. is the problem?
Here is the original question.
Password Hashing - Why salt 60,000 times
Problem is these hashes do not match if (resultHash.Equals(hashPassword))
Code
public string BuildVerify()
{
string password = "";
string salt = "";
byte[] result;
using (var sha256 = SHA256.Create())
{
password = "hovercraft";
// step 1: you can use RNGCryptoServiceProvider for something worth using
var passwordHashing = new PasswordHashing();
salt = passwordHashing.CreateRandomSalt();
// step 2
string hash =
Convert.ToBase64String(sha256.ComputeHash(Encoding.UTF8.GetBytes(salt + password)));
// step 3
result = sha256.ComputeHash(Encoding.UTF8.GetBytes(salt + hash));
// step 4
for (int i = 0; i < 60000; i++)
{
result =
sha256.ComputeHash(Encoding.UTF8.GetBytes(salt + Convert.ToBase64String(result)));
}
}
// TESTING VERIFY this works ..
string SaltAndPwd = string.Concat(password, salt);
SHA256 sha2 = SHA256Managed.Create();
byte[] buff = sha2.ComputeHash(Encoding.Unicode.GetBytes(SaltAndPwd));
string resultHash = Convert.ToBase64String(buff);
string hashPassword = Convert.ToBase64String(result);
if (resultHash.Equals(hashPassword))
{
// perfect
}
return "";
}
public class PasswordHashing
{
public string CreateRandomSalt()
{
string password = "";
password = HashPassword.CreateSalt(8) + "=";
password = password.Replace("/", "c");
return password;
}
}
public static string CreateSalt(int size)
{
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] buff = new byte[size];
rng.GetBytes(buff);
return Convert.ToBase64String(buff);
}
Update - issue
Ok, I'm using the code from the answer, but obviously my assumptions are not correct as I cannot use my code to verify
// This should be stored in your DB for example along with the hash result
var newsalt = SOPasswordHasher.GetSalt();
// We calculate the hash then store the result. Next time you want to authenticate someone
// You'll have to reuse the same salt and recalculate the hash then compare
// the stored hash with the new one
var result = Convert.ToBase64String(SOPasswordHasher.Hash("hovercraft", newsalt));
string SaltAndPwd = string.Concat("hovercraft", newsalt);
SHA256 sha2 = SHA256Managed.Create();
byte[] buff = sha2.ComputeHash(Encoding.Unicode.GetBytes(SaltAndPwd));
string resultHash = Convert.ToBase64String(buff);
if (result.Equals(resultHash))
{
// perfect
}
解决方案 Here's a reusable class that you can use (relying less on converting to base64):
class SOPasswordHasher
{
/// <summary>
/// Password Hasher
/// </summary>
/// <param name="password">The password you want to hash</param>
/// <param name="salt">byte array of (crypto-secure) random values</param>
/// <param name="iterations">Number of iterations. default is 60,000</param>
/// <returns>Byte array containing the hashed password</returns>
public static byte[] Hash(string password, byte[] salt, int iterations = 60000)
{
using (var sha256 = SHA256.Create())
{
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
// step 2
byte[] hash = sha256.ComputeHash(passwordBytes.Concat(salt).ToArray());
// step 3
byte[] result = sha256.ComputeHash(salt.Concat(hash).ToArray());
// step 4
for (int i = 0; i < iterations; i++)
{
result =
sha256.ComputeHash(salt.Concat(result).ToArray());
}
return result;
}
}
public static byte[] GetSalt(int size = 32)
{
byte[] salt = new byte[size];
using (var cryptoServiceProvider = new RNGCryptoServiceProvider())
{
cryptoServiceProvider.GetBytes(salt);
}
return salt;
}
}
and here's a usage example:
// This should be stored in your DB for example along with the hash result
var salt = SOPasswordHasher.GetSalt();
// We calculate the hash then store the result. Next time you want to authenticate someone
// You'll have to reuse the same salt and recalculate the hash then compare
// the stored hash with the new one
var result = Convert.ToBase64String(SOPasswordHasher.Hash("hovercraft", salt));
Important: I make no guarantee that this code is safe to use since I'm not a security expert. Bruce Schneier said it best: "Amateurs Produce Amateur Cryptography"
这篇关于验证散列密码不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!