7

HMACSHA1 インスタンスを保持する静的 (共有) 変数を使用することが asp.net ページのコード ビハインドで危険であるかどうか自問しています。問題は、同じ asp.net ページで複数の同時要求を処理するときに、すべての asp.net ワーカー プロセスのスレッドで同じ HMACSHA1 インスタンスが使用されることです。ComputeHash() によって使用/変更されるすべての (HMACSHA1) インスタンスおよび ComputeHash() メソッド変数は、すべてのスレッドによって共有される (= 変更される可能性がある) ?! その仮定は正しいですか?その結果、ComputeHash の戻り値が正しいとは限りません?!?! したがって、すべてのasp.netスレッドで静的/共有HMACSHA1インスタンスを使用することは許可されていません..

あなたがこの問題についてどう思うか気になります。

これに対する唯一の解決策は、ComputeHash() メソッドのクリティカル パスなどの sth です。しかし、それは「私たちの手の届かないところ」です..

よろしく、クリス

4

4 に答える 4

9

クアッドコア HT CPU でハッシュ計算を実行する 8 つまたは 16 の並列タスクを実行すると、SHA256Cng.ComputeHash から不明な暗号化例外が発生しました。

ComputeHash にロック セマンティクスを追加することで問題が解決しました。そのため、少なくとも SHA256Cng バージョンはスレッド セーフではないようです。

于 2011-11-13T23:27:02.807 に答える
6

KeyedHashAlgorithm.ComputeHash()同じ に対して非決定論的な結果が得られるため、それはスレッドセーフではないことを知っておく価値がありますKeyedHashAlgorithm.Key

私の場合、KeyedHashAlgorithm をキャッシュしたいのは、クライアント側からの信頼性KeyedHashAlgorithm.Keyを検証するために常に同じであるためです。おそらく、内部変数をインスタンスにキャッシュします。スレッドごとにインスタンスをキャッシュする必要があります。これはテストです:ComputeHash()KeyedHashAlgorithmThreadStaticThreadLocal

静的KeyedHashAlgorithmは一貫性のない結果をもたらします:

var kha = KeyedHashAlgorithm.Create("HMACSHA256");
kha.Key = Encoding.UTF8.GetBytes("key");
Action comp = () =>
{
    var computed = kha.ComputeHash(Encoding.UTF8.GetBytes("message"));
    Console.WriteLine(Convert.ToBase64String(computed));
};
Parallel.Invoke(comp, comp, comp, comp, comp, comp, comp, comp);

KeyedHashAlgorithmスレッドごとの比較:

ThreadLocal<KeyedHashAlgorithm> tl= new ThreadLocal<KeyedHashAlgorithm>(() =>
{
    var kha = KeyedHashAlgorithm.Create("HMACSHA256");
    kha.Key = Encoding.UTF8.GetBytes("key");
    return kha;
});
Action comp = () =>
{
    var computed = tl.Value.ComputeHash(Encoding.UTF8.GetBytes("message"));
    Console.WriteLine(Convert.ToBase64String(computed));
};
Parallel.Invoke(comp, comp, comp, comp, comp, comp, comp, comp);

このコードは、「スレッド セーフ」の結果について他の関数をテストするために使用できます。これが他の人に役立つことを願っています。

于 2014-11-11T07:21:28.803 に答える
6

ハッシュ アルゴリズムは決定論的であり、特定の入力に対して毎回同じハッシュを返す必要があります。

毎回同じキーを使用する限り、それらを静的にする必要はありません。ただし、パラメーターなしのコンストラクターを使用して HMACSHA1 インスタンスを構築している場合は、ランダムなキーが生成されます。KeyValue プロパティからランダムな値を取得し、ハッシュと共に保存する必要があります。

静的インスタンスを使用することは間違いなく危険です。Thread1 が計算する値を設定し、Thread1 が ComputerHash() を呼び出す前に Thread2 が値を設定した場合、Thread1 は Thread2 の値のハッシュを取得します。いずれかのスレッドがキーを設定している場合も同じことが起こります。

于 2009-02-20T14:22:02.340 に答える
1

ロックせずにスレッド セーフが必要な場合は、ThreadStatic 属性を使用して、次のように各スレッドに一意のインスタンスを作成できます。

[ThreadStatic]
private static HMACSHA1 _hmacSha1;

public static HMACSHA1 HmacSha1
{
    get 
    {
        if (_hmacSha1 == null)
        {
            // this will happen once on each thread
            _hmacSha1 = new HMACSHA1(GetKeyBytes());
        }               

        return _hmacSha1;
    }
}

さて、2つの補足事項:

  1. スレッド静的フィールドへのアクセスは、通常の静的フィールドへのアクセスよりも大幅に時間がかかります。そのため、スレッド静的バージョンが適している場合とそうでない場合があります。

  2. これをページ リクエストごとに 1 回行う場合、違いは非常に小さいため、どちらのアプローチを選択しても問題ありません。これを非常にタイトなループで行っていた場合、またはロック セクションのコードに非常に長い時間がかかった場合、選択が重要になる可能性があります。

于 2014-10-03T17:46:33.190 に答える