1. ホーム
  2. c#

[解決済み] ASP.NET IdentityのデフォルトのPassword Hasher - その仕組みと安全性とは?

2022-04-21 15:28:53

質問

でデフォルトで実装されているPassword Hasherは、どのようなものなのでしょうか? ユーザー マネージャー MVC 5とASP.NET Identity Frameworkに付属しているASP.NET Identity Frameworkは、十分に安全なのでしょうか?そして、もしそうなら、それがどのように機能するかについて説明してもらえますか?

IPasswordHasherのインターフェースはこのようになっています。

public interface IPasswordHasher
{
    string HashPassword(string password);
    PasswordVerificationResult VerifyHashedPassword(string hashedPassword, 
                                                       string providedPassword);
}

見ての通り、塩がかかりませんが、このスレッドで紹介されている:" Asp.net Identity パスワードハッシュ化 となります。 裏側で実際に塩漬けにしていること。では、どのようにこれを行うのでしょうか?また、このソルトはどこから来るのでしょうか?

私の懸念は、ソルトが静的であるため、非常に安全でないことです。

解決するには?

以下は、デフォルトの実装( ASP.NETフレームワーク または ASP.NET Core )が動作します。それは 鍵の導出機能 とランダムなソルトでハッシュを生成します。ソルトはKDFの出力の一部として含まれます。従って、同じパスワードをハッシュ化するたびに、異なるハッシュが生成されます。ハッシュを検証するために、出力はソルトと残りに分割され、指定されたソルトを持つパスワードに対してKDFが再度実行される。その結果が最初の出力の残りと一致すれば、そのハッシュは検証されたことになる。

ハッシュ化する

public static string HashPassword(string password)
{
    byte[] salt;
    byte[] buffer2;
    if (password == null)
    {
        throw new ArgumentNullException("password");
    }
    using (Rfc2898DeriveBytes bytes = new Rfc2898DeriveBytes(password, 0x10, 0x3e8))
    {
        salt = bytes.Salt;
        buffer2 = bytes.GetBytes(0x20);
    }
    byte[] dst = new byte[0x31];
    Buffer.BlockCopy(salt, 0, dst, 1, 0x10);
    Buffer.BlockCopy(buffer2, 0, dst, 0x11, 0x20);
    return Convert.ToBase64String(dst);
}

検証中です。

public static bool VerifyHashedPassword(string hashedPassword, string password)
{
    byte[] buffer4;
    if (hashedPassword == null)
    {
        return false;
    }
    if (password == null)
    {
        throw new ArgumentNullException("password");
    }
    byte[] src = Convert.FromBase64String(hashedPassword);
    if ((src.Length != 0x31) || (src[0] != 0))
    {
        return false;
    }
    byte[] dst = new byte[0x10];
    Buffer.BlockCopy(src, 1, dst, 0, 0x10);
    byte[] buffer3 = new byte[0x20];
    Buffer.BlockCopy(src, 0x11, buffer3, 0, 0x20);
    using (Rfc2898DeriveBytes bytes = new Rfc2898DeriveBytes(password, dst, 0x3e8))
    {
        buffer4 = bytes.GetBytes(0x20);
    }
    return ByteArraysEqual(buffer3, buffer4);
}