Oki所以我想通过在.Net中添加随机盐来哈希我的密码.我用于此目的的内置类是RNGCryptoServiceProvider – 生成随机盐和Rfc2898DeriveBytes – 来散列实际密码.
但是当我将Rfc2898DeriveBytes的GetBytes()函数调用为passwordString,SaltBytes&的相同组合时.迭代计数结果不同.
我粘贴我的代码以供参考
public class PBKDF2Implementation
{
int minSaltSize = 32;
int maxSaltSize = 64;
public string CreateHash(string plainText , out string salt)
{
Random random = new Random();
int saltSize = random.Next(minSaltSize, maxSaltSize);
// Allocate a byte array, which will hold the salt.
byte[] saltBytes = new byte[saltSize];
// Initialize a random number generator.
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
// Fill the salt with cryptographically strong byte values.
rng.GetNonZeroBytes(saltBytes);
string strSalt = System.Text.Encoding.ASCII.GetString(saltBytes);
//string strSalt = System.Convert.ToBase64String(saltBytes);
salt = strSalt;
Console.WriteLine(saltBytes.Count());
Console.WriteLine(strSalt);
Rfc2898DeriveBytes pwdGen = new Rfc2898DeriveBytes(plainText, saltBytes, 1000);
// generate an RC2 key
byte[] key = pwdGen.GetBytes(32);
Console.WriteLine(System.Convert.ToBase64String(key));
return System.Convert.ToBase64String(key);
}
public bool CompareHash(string plainText, string salt, string hashValue)
{
byte[] saltBytes = System.Text.Encoding.ASCII.GetBytes(salt);
//byte[] saltBytes = System.Convert.FromBase64String(salt);
Console.WriteLine(saltBytes.Count());
Console.WriteLine(System.Text.Encoding.ASCII.GetString(saltBytes));
Rfc2898DeriveBytes pwdGen = new Rfc2898DeriveBytes(plainText, saltBytes, 1000);
// generate an RC2 key
byte[] key = pwdGen.GetBytes(32);
Console.WriteLine(System.Convert.ToBase64String(key));
return System.Convert.ToBase64String(key) == hashValue;
}
}
在我的测试课中,我有这个功能
[Test]
public void shouldGenerateConsistentHash()
{
PBKDF2Implementation cPbkdf2Implementation = new PBKDF2Implementation();
string salt;
string hashValue = cPbkdf2Implementation.CreateHash("password", out salt);
bool result = cPbkdf2Implementation.CompareHash("password", salt, hashValue);
Assert.IsTrue(result) ;
}
测试失败.
但如果在上面的类PBKDF2Implementation中,如果我替换行
带有System.Text.Encoding.Unicode.GetString的System.Text.Encoding.ASCII.GetString
和
带有System.Text.Encoding.Unicode.GetBytes的System.Text.Encoding.ASCII.GetBytes
测试通过.知道为什么会这样吗?
我想让它与ASCII编码一起工作的原因是因为存储这个哈希值的同一个DB也将被PHP应用程序&只有当salt编码为ASCII时,由PBKDF2实现的PHP生成的哈希值才匹配Rfc2898DeriveBytes的哈希值.
这是同样的PHP实现
http://www.php.net/manual/en/function.hash-hmac.php#101540
解决方法:
>避免使用加密字符串.使用字节数组,即byte []
>如果必须使用字符串,请特别注意编码.他们会在10次中咬你9次;
例如.
byte [] data = new byte [] { 65, 0, 65 };
var s = System.Text.Encoding.ASCII.GetString (data);
什么是价值?
答案:“A”
如果你从同一个字符串中询问byte [],你会得到:byte [1] {65},它与原始字符串不同,并且不适用于大多数加密用法.
Base64更安全,因为它将保持每个字节完整.