Okiだから、.Netにランダムなソルトを追加してパスワードをハッシュしたいと思います。この目的で使用している組み込みクラスは、ランダムソルトを生成するためのRNGCryptoServiceProviderと、実際のパスワードをハッシュするためのRfc2898DeriveBytesです。
しかし、passwordString、SaltBytes、およびIteration countの同じ組み合わせに対してRfc2898DeriveBytesのGetBytes()関数を呼び出すと、結果が異なります。参照用にコードを貼り付けています
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.ASCII.GetStringからSystem.Text.Encoding.Unicode.GetStringに、System.Text.Encoding.ASCII.GetBytesをSystem.Text.Encoding.Unicodeに置き換えます。 GetBytes
テストに合格します。なぜこれが起こっているのか考えていますか?ASCIIエンコーディングで動作させたい理由は、このハッシュ値が格納されているのと同じDBがPHPアプリケーションでも使用され、PHPのPBKDF2実装によって生成されたハッシュ値がRfc2898DeriveBytesのハッシュ値と一致するのはソルトエンコーディングがASCII。
これは、同じhttp://www.php.net/manual/en/function.hash-hmac.php#101540のPHP実装です 。