41

.Net 4.5 にアップグレードした後、「System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile は廃止されました」という警告が表示され、代わりにメンバーシップ API を使用するよう提案されました。

これはすべて非常にうまく機能しており、新しいプロジェクトには適していますが、この段階 (ユーザー データとハッシュ化されたパスワードが存在する状態) では、ハッシュ化の方法が異なる可能性があるカスタム メンバーシップ プロバイダーに変更することはできません。

このような問題の推奨される方法は何ですか? 「廃止された」呼び出しを引き続き使用することは、明らかに推奨される方法ではありません。そのため、「メンバーシップ API を使用する」以外のものに置き換えられましたか?

4

4 に答える 4

57

これは SHA1 バリアントのソリューションです。

     public static string GetSwcSHA1(string value)
     {
        SHA1 algorithm = SHA1.Create();
        byte[] data = algorithm.ComputeHash(Encoding.UTF8.GetBytes(value));
        string sh1 = "";
        for (int i = 0; i < data.Length; i++)
        {
            sh1 += data[i].ToString("x2").ToUpperInvariant();
        }
        return sh1;
     }

MD5 の場合、アルゴリズムを次のように変更するだけです。

MD5 algorithm = MD5.Create();

上記のコードの VB.NET バリアントを追加するだけです。

    Public Shared Function CreateHash(saltAndPassword) As String
        Dim Algorithm As SHA1 = SHA1.Create()
        Dim Data As Byte() = Algorithm.ComputeHash(Encoding.UTF8.GetBytes(saltAndPassword))
        Dim Hashed As String = ""

        For i As Integer = 0 To Data.Length - 1
            Hashed &= Data(i).ToString("x2").ToUpperInvariant()
        Next

        Return Hashed
    End Function
于 2012-12-13T12:06:33.207 に答える
9

このような問題の推奨される方法は何ですか? 「廃止された」呼び出しを引き続き使用することは、明らかに推奨される方法ではありません。そのため、「メンバーシップ API を使用する」以外のものに置き換えられましたか?

純粋に .NET Framework 内で (除外した) 最善の方法は、PBKDF2、Bcrypt、または Scrypt によってパスワードがハッシュされるようにすべてを変更することです。PBKDF2 は、 Rfc2898DeriveBytes クラスによって .NET で提供されます。

2 番目に良い方法は、最終的に 2 つの「バージョン」のパスワードを使用することです。

  • バージョン 0 は古い HashPasswordForStoringInConfigFile でしたが、それらを一括してオフラインでバージョン 1 に更新し、誰かがそれらを盗む前にそれらの古いハッシュを完全に削除すると、哀れな 90 年代のビンテージ パスワード ハッシュとして業界ニュースに掲載されることになります。
  • バージョン 1、これは既存の HashPasswordForStoringInConfigFile 値の PBKDF2 です! つまり、現在の厄介な古いハッシュを取得し、それらを新しいランダムソルトと多数の反復で PBKDF2 し、結果を保存します。次に、ユーザーがログインしたいときに、@RichardBažant が書いたコードにパスワードを入力して、HashPasswordForStoringInConfigFile が返すものを取得し、その結果に PBKDF2 を適用します!
    • つまり、実際には Rfc2898DeriveBytes(HashPasswordForStoringInConfigFile(password)),PerUserSalt,YourIterations) です。
  • バージョン 1 ハッシュを持つユーザーがアップグレードされるバージョン 2。「バージョン」以外の列はすべて同じですが、バージョン 1 を計算して検証した後、Rfc2898DeriveBytes(password),PerUserSalt,YourIterations) を計算し、バージョン 1 のハッシュをバージョン 2 のハッシュに置き換えます (そしてバージョンを 2 に変更します)。もちろん)。

3 番目に良い方法は 2 番目に良い方法ですが、バージョン 1 しかありません。注意してください。この方法はDCC2 の狂気です。古い出力を新しいアルゴリズム内にラップし続けます。

どちらの場合も、PBKDF2-HMAC-SHA-1 の結果をデータベースに保存するため、次のものが必要になります。

  • パスワード ハッシュ (BINARY(20)) - つまり、PBKDF2 出力。
  • あなたのソルト (BINARY(16)、RNGCryptoServiceProvider Classによってユーザーごとに生成されます)
  • オプション: PBKDF2 反復回数 (INT、数万から始まり、サーバーが最大負荷で CPU バウンドになる直前まで。ハードウェアがアップグレードされるにつれて増加します)
    • これにより、ユーザーが (正しい) パスワードを入力するたびに、セキュリティ レベルを透過的に高めることができます。最初にパスワードが正しいことを検証し、次に反復回数を増やして再ハッシュすることにより、
  • オプション: 一度に複数のバージョンをアクティブにできるため、後で別のアルゴリズムに簡単にアップグレードできるようにするための「バージョン」(TINYINT)。

PS バージョン 1 またはバージョン 2 の新しいアルゴリズムの場合、Jither は PBKDF2-HMAC-SHA256、PBKDF2-HMAC-SHA512 などに対応する .NET ライブラリを作成しました。私のGithubリポジトリには、合理的なテストベクトルのセットを備えたバリアントが含まれています。

于 2014-02-25T04:19:52.127 に答える
3

.Netで最も単純なものを使用できないのはなぜですか

public static string HashString(string inputString, string hashName)
{
  var algorithm = HashAlgorithm.Create(hashName);
  if (algorithm == null)
     throw new ArgumentException("Unrecognized hash name", hashName);

  byte[] hash = algorithm.ComputeHash(Encoding.UTF8.GetBytes(inputString));
  return Convert.ToBase64String(hash);
}
于 2016-04-30T20:34:34.553 に答える
2

リチャードの答えは私にとってうまくいきました。これは、.NET Framework 4.5 から逆コンパイルされたコードです。誰かの方が良い場合は、それを使用してください。もう少し速いかも知れません。

        public static string BinaryToHex(byte[] data)
        {
            if (data == null)
            {
                return null;
            }
            char[] hex = new char[checked((int)data.Length * 2)];
            for (int i = 0; i < (int)data.Length; i++)
            {
                byte num = data[i];
                hex[2 * i] = NibbleToHex((byte)(num >> 4));
                hex[2 * i + 1] = NibbleToHex((byte)(num & 15));
            }
            return new string(hex);
        }

        private static char NibbleToHex(byte nibble)
        {
            int aChar = (nibble < 10 ? nibble + 48 : nibble - 10 + 65);
            return (char)aChar;
        }
于 2013-08-12T13:53:48.647 に答える