4

今日、Webアプリケーションを.net 4.0に移動しましたが、FormsAuthが機能しなくなりました。SqlMembershipProvider(組み込みのSqlMembershipProviderの簡略化されたバージョン)を数時間調べた後、HMACSHA256ハッシュに一貫性がないことがわかりました。これは暗号化方法です:

internal string EncodePassword(string pass, int passwordFormat, string salt)
{
    if (passwordFormat == 0) // MembershipPasswordFormat.Clear
        return pass;

    byte[] bIn = Encoding.Unicode.GetBytes(pass);
    byte[] bSalt = Convert.FromBase64String(salt);
    byte[] bAll = new byte[bSalt.Length + bIn.Length];
    byte[] bRet = null;

    Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
    Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);
    if (passwordFormat == 1)
    { // MembershipPasswordFormat.Hashed
        HashAlgorithm s = HashAlgorithm.Create( Membership.HashAlgorithmType );
        bRet = s.ComputeHash(bAll);
    } else
    {
        bRet = EncryptPassword( bAll );
    }

    return Convert.ToBase64String(bRet);
}

同じパスワードとsaltを2回渡すと、異なる結果が返されます!!! .NET3.5では完全に機能していました

重大な変更を知っている人はいますか、それとも既知のバグですか?

更新:ハッシュアルゴリズムとしてSHA512を指定すると、すべてが正常に機能するため、.NET4.0でのHMACSHA256ハッシュアルゴリズムの実装のバグだと思います。

ありがとう!アンドレイ

4

2 に答える 2

2

.net 4.0 にはセキュリティ関連の変更がいくつかあったと思います。こちらをご覧ください ...

http://www.asp.net/(S(ywiyuluxr3qb2dfva1z5lgeg))/learn/whitepapers/aspnet4/breaking-changes

最初に目立つのはこれです...

デフォルトのハッシュ アルゴリズムは HMACSHA256 になりました

ASP.NET は、暗号化アルゴリズムとハッシュ アルゴリズムの両方を使用して、フォーム認証 Cookie やビュー ステートなどのデータをセキュリティで保護します。デフォルトでは、ASP.NET 4 は Cookie とビュー ステートのハッシュ操作に HMACSHA256 アルゴリズムを使用するようになりました。ASP.NET の以前のバージョンでは、古い HMACSHA1 アルゴリズムが使用されていました。

フォーム認証 Cookie などのデータが複数の .NET Framework バージョンで機能する必要がある ASP.NET 2.0 と ASP.NET 4 が混在する環境を実行すると、アプリケーションが影響を受ける可能性があります。古い HMACSHA1 アルゴリズムを使用するように ASP.NET 4 Web アプリケーションを構成するには、Web.config ファイルに次の設定を追加します。

      <machineKey validation="SHA1" />

ハッシュアルゴリズムを明示的に設定しましたか、それともasp.netに決定させましたか...別のデフォルトを使用している場合、定義されたハッシュアルゴリズムがサポートされなくなったため、古いハッシュアルゴリズムをランダムに取得している可能性があります。

そうは言っても、M $ はあなたが使用しているものを廃止した可能性があるため、それが原因である可能性があります.... CMSをテストする必要があることに気づきました.

頭を上げてくれてありがとう、うまくいけば、私の考えが私たち両方に役立つことを願っています!!!

于 2010-05-19T15:57:59.323 に答える
2

私もこの問題に遭遇しました。

私の状況では、最終的な目標は、connectionString を動的に設定できるようにすることでした (web.config にハードコーディングするのではなく)。これを行うには、MS が ASP.NET プロバイダー用に公開したソース コードをダウンロードし、接続文字列を取得するための内部機能の一部を変更しました。

ただし、これはすべて .NET 2.0 用であり、Andrey が上に投稿したコードとまったく同じように見えます。すべてが整ったら、自分の Web サイトにログインできないことに気付きました。それで検索したらこんな記事を見つけました。ありがとう!

私は先に進み、.NET Framework 4.0 のコードをダウンロードしました。(もし知りたい人がいれば) ここに新しいバージョンの EncodePassword メソッドがあります。これを古いバージョンの SqlMembershipProvider にコピーして、新しい暗号化方法を使用し、ASP.NET 4.0 Web サイトに再度ログインできるようにする予定です。

    private string EncodePassword(string pass, int passwordFormat, string salt)
    { 
        if (passwordFormat == 0) // MembershipPasswordFormat.Clear
            return pass;

        byte[] bIn = Encoding.Unicode.GetBytes(pass); 
        byte[] bSalt = Convert.FromBase64String(salt);
        byte[] bRet = null; 

        if (passwordFormat == 1)
        { // MembershipPasswordFormat.Hashed 
            HashAlgorithm hm = GetHashAlgorithm();
            if (hm is KeyedHashAlgorithm) {
                KeyedHashAlgorithm kha = (KeyedHashAlgorithm) hm;
                if (kha.Key.Length == bSalt.Length) { 
                    kha.Key = bSalt;
                } else if (kha.Key.Length < bSalt.Length) { 
                    byte[] bKey = new byte[kha.Key.Length]; 
                    Buffer.BlockCopy(bSalt, 0, bKey, 0, bKey.Length);
                    kha.Key = bKey; 
                } else {
                    byte[] bKey = new byte[kha.Key.Length];
                    for (int iter = 0; iter < bKey.Length; ) {
                        int len = Math.Min(bSalt.Length, bKey.Length - iter); 
                        Buffer.BlockCopy(bSalt, 0, bKey, iter, len);
                        iter += len; 
                    } 
                    kha.Key = bKey;
                } 
                bRet = kha.ComputeHash(bIn);
            }
            else {
                byte[] bAll = new byte[bSalt.Length + bIn.Length]; 
                Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
                Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length); 
                bRet = hm.ComputeHash(bAll); 
            }
        } else { 
            byte[] bAll = new byte[bSalt.Length + bIn.Length];
            Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
            Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);
            bRet = EncryptPassword(bAll, _LegacyPasswordCompatibilityMode); 
        }

        return Convert.ToBase64String(bRet); 
    }

編集: この 1 つのメソッドを SqlMembershipProvider の古いバージョンにコピーしようとするのは悪い考えでした。あまりにも多くのことが変更されました。:(

于 2010-08-20T04:18:15.480 に答える