0

zeteticには、bcrypt2のサポートを含む非常に優れた暗号化ライブラリがあります。ASP.NETメンバーシッププロバイダーに組み込むのは簡単なようです(実際、デフォルトプロバイダーの手順はここにあります)。EncodePassword関数にSHA1ハッシュ形式をハードコーディングしているように見えるNHibernateメンバーシッププロバイダー(ここにあります)を使用しています。私の質問は、これをBCrypt2(特にZeteticのラッパー)で動作するようにどのように適合させるべきかということです。これは私が間違っていることを非常に恐れていることであり、それが「機能する」はずではないが、私が見つける資格がないいくつかの隠れた欠陥があるので、自分でそれを突き刺すことには消極的です。

 private string EncodePassword(string password)
        {
            string encodedPassword = password;

            switch (PasswordFormat)
            {
                case MembershipPasswordFormat.Clear:
                    break;
                case MembershipPasswordFormat.Encrypted:
                    encodedPassword =
                        Convert.ToBase64String(EncryptPassword(Encoding.Unicode.GetBytes(password)));
                    break;
                case MembershipPasswordFormat.Hashed:
                    HMACSHA1 hash = new HMACSHA1();
                    hash.Key = HexToByte(_machineKey.ValidationKey);
                    encodedPassword =
                        Convert.ToBase64String(hash.ComputeHash(Encoding.Unicode.GetBytes(password)));
                    break;
                default:
                    throw new ProviderException("Unsupported password format.");
            }

            return encodedPassword;
        }
4

1 に答える 1

1

NHibernateベースのメンバーシッププロバイダーを変更しますか、それともそのまま使用し続けますか?後者の場合、拡張性はないように見えます。

ASP.NET SqlMembershipProviderは、ハッシュアルゴリズムの名前を受け入れることで機能し、HashAlgorithm.Create(name)を介してインスタンスを呼び出し、アルゴリズムの種類がKeyedHashAlgorithmまたは通常の(キーなしの)HashAlgorithmであることが判明した場合、動作が少し異なります。Zetetic.Securityパッケージは、BCryptとPBKDF2をそのモデルと互換性のあるものにするためのほんの少しの接着剤を提供しています。

NHMembershipProviderのサンプルコードは、HMACSHA1に直接依存しているため、これを利用できません。HMACSHA1は、この目的のための安全なアルゴリズムではなく、すべてのユーザーに静的ソルトを使用することもできません(ソルトがない場合よりもほとんど優れていません)。アプリValidationKeyとHMACSHA1は、メッセージの整合性のみを目的としています。

サンプルは次のとおりです。

public class HashDemo
{
    private static readonly RNGCryptoServiceProvider s_rng = new RNGCryptoServiceProvider();

    public string HashPassword(string pwd, string hashName)
    {
        var alg = HashAlgorithm.Create(hashName);

        if (alg == null)
            throw new ArgumentException("Invalid hash name", "hashName");

        byte[] tohash = System.Text.Encoding.UTF8.GetBytes(pwd);

        var ka = alg as KeyedHashAlgorithm;

        if (ka != null)
        {
            if (ka.Key == null || ka.Key.Length == 0)
            {
                byte[] key = new byte[20];

                s_rng.GetBytes(key);

                ka.Key = key;
            }
            else
            {
                s_rng.GetBytes(ka.Key);
            }
            // TODO: return base64(ka.Key || alg.ComputeHash(tohash))
        }
        else
        {
            var salt = new byte[20];

            s_rng.GetBytes(salt);

            using (var ms = new System.IO.MemoryStream(salt))
            {
                ms.Write(tohash, 0, tohash.Length);

                tohash = ms.ToArray();
            }
            // TODO: return base64(salt || alg.ComputeHash(tohash))
        }
    }
}
于 2012-06-13T17:11:14.803 に答える