質問

だから、ハッシュアルゴリズムのさまざまな実装に大きな違いがあるのではないかと思っていました。たとえば、SHAシリーズのアルゴリズムを考えてみましょう。それらはすべて3つの実装を持ち、1つはマネージコードで、2つは異なるネイティブ暗号化APIのラッパーですが、いずれかを使用することで大きな違いはありますか?ラッパーバージョンはネイティブコードで実行されるため、パフォーマンスが向上する可能性がありますが、まったく同じ計算を実行する必要があるため、同じ出力を提供する必要があります。これは正しいですか?

たとえば、SHA512CNGはXP SP2では使用できません(ドキュメントは間違っています)が、SHA512MANAGEDは使用できます。


@Maxim-ありがとうございます。しかし、私が求めていたものではありません。特定のハッシュアルゴリズムのManaged / CryptoServiceProvider / CNG実装を使用した場合と、パフォーマンス以外に違いがあるかどうかを尋ねていました。 .NET 3.5では、3つの実装ですべてのハッシュアルゴリズムを取得できるため、

SHA512Managed SHA512CryptoServiceProvider SHA512Cng

後者の2つは、ネイティブAPIのラッパーです。これは、たとえばすべてのSHAxxx実装に当てはまります。

役に立ちましたか?

解決

1つの違いは、ネイティブバージョン(少なくともそれらのいくつか)はFIPS認定(つまり、米国政府によって承認)であるのに対して、管理バージョンはそうではないことです。 「FIPSのみ」として設定されているWindowsマシンでコードが実行されている場合、管理バージョンの使用は失敗します。

ほとんどのWindowsマシンはそのようには構成されていませんが、政府または防衛指向の(または他の高度に安全な)環境に展開している場合、この状況に陥る可能性があります。

http://blogs.msdn.com/shawnfaを参照/archive/2005/05/16/417975.aspx

他のヒント

Cngバージョンはもう少し速いはずですが、それぞれの速度を比較する小さなプログラムを作成しました。 (MD5とSHA1のパフォーマンス特性について尋ねているクライアントがいました)

MD5とSHA1の違いがほとんどないことを知って驚きましたが、CngとCryptoServiceProviderにわずかな違いがあることにも驚きました。

ソースは非常に単純で、同じ反復を複数回行うために担当者を追加したので、実行中にマシン上で異常が発生した場合に平均化できます。

次のような呼び出しで次を呼び出します。

CalculateHash(1, 1024, new SHA1CryptoServiceProvider());

static long CalculateHash(UInt64 repetitions, UInt64 size, HashAlgorithm engine)
    {
        RandomNumberGenerator rng = RandomNumberGenerator.Create();

        byte[][] goo = new byte[repetitions][];
        for (UInt64 i = 0; i < repetitions; i++)
        {
            goo[i] = new byte[size];
            rng.GetBytes(goo[i]);
        }

        DateTime start = DateTime.Now;
        for (UInt64 i = 0; i < repetitions; i++)
        {
            engine.ComputeHash(goo[i]);
        }
        return DateTime.Now.Subtract(start).Ticks;
    }

大きな入力または小さな入力を使用しているときに転倒したかどうかを判断するために、これをサイズの増加するループで実行しました。ここにループがあり、データが続きます(私のコンピューターは2 ^ 28でRAMを使い果たしました):

int loops = 32;
        UInt64 reps = 1;

        int width = 20;
        Console.WriteLine("Loop#".PadRight(6) +
                "MD5".PadRight(width) +
                "SHA1".PadRight(width) +
                "SHA1Cng".PadRight(width) +
                "SHA256".PadRight(width) +
                "SHA256Cng".PadRight(width));

        for (int i = 0; i < loops; i++)
        {
            UInt64 size = (UInt64)Math.Pow((double)2, (double)i);

            Console.WriteLine((i + 1).ToString().PadRight(6) +
                CalculateHash(reps, size, new MD5CryptoServiceProvider()).ToString().PadRight(width) +
                CalculateHash(reps, size, new SHA1CryptoServiceProvider()).ToString().PadRight(width) +
                CalculateHash(reps, size, new SHA1Cng() ).ToString().PadRight(width) +
                CalculateHash(reps, size, new SHA256CryptoServiceProvider()).ToString().PadRight(width) +
                CalculateHash(reps, size, new SHA256Cng()).ToString().PadRight(width));
        }

Loop# MD5         SHA1        SHA1Cng     SHA256      SHA256Cng
1     50210       0           0           0           0
2     0           0           0           0           0
3     0           0           0           0           0
4     0           0           0           0           0
5     0           0           0           0           0
6     0           0           0           0           0
7     0           0           0           0           0
8     0           0           0           0           0
9     0           0           0           0           0
10    0           0           10042       0           0
11    0           0           0           0           0
12    0           0           0           0           0
13    0           0           0           0           0
14    0           0           0           0           0
15    10042       0           0           10042       10042
16    10042       0           0           0           0
17    0           0           0           10042       10042
18    0           10042       10042       20084       10042
19    0           10042       10042       30126       40168
20    20084       20084       20084       70294       70294
21    30126       40168       40168       140588      140588
22    60252       70294       80336       291218      281176
23    120504      140588      180756      572394      612562
24    241008      281176      361512      1144788     1215082
25    482016      572394      723024      2289576     2420122
26    953990      1134746     1456090     4538984     4830202
27    1907980     2259450     2982474     9118136     9660404
28    3805918     4508858     5804276     18336692    19581900

SHA512で CNG managed をすばやく汚い比較をしました。これは、以下のコードを使用して、すべてのSHAアルゴリズムの中で最も遅いです。

    static void Main(string[] args)
    {
      int loops = 10000000;
      var data = Encoding.ASCII.GetBytes("123");

      var hashLoop = new Action<HashAlgorithm>((HashAlgorithm ha) =>
      {
        for (int i = 0; i < loops; i++)
          ha.ComputeHash(data);
      });

      var t1 = Task.Factory.StartNew(() =>
      {
        Time(hashLoop, new SHA512Managed());
      });
      var t2 = Task.Factory.StartNew(() =>
      {
        Time(hashLoop, new SHA512Cng());
      });

      Task.WaitAll(t1, t2);
      Console.WriteLine("Benchmark done!");
      Console.ReadKey();
    }
    static void Time(Action<HashAlgorithm> action, HashAlgorithm ha)
    {
      var sw = new Stopwatch();
      sw.Start();
      action(ha);
      sw.Stop();
      Console.WriteLine("{1} done in {0}ms", sw.ElapsedMilliseconds, ha.ToString());
    }

複数回実行した後、CNGはアルゴリズムのマネージドバージョンよりもかなり高速であり、約 21.7%から49.5%

であることがわかりました。

マネージドバージョンとCNGバージョンのもう1つの違いは、サポートされている.Net Frameworkバージョンです。例:

  • AES Managedバージョンは3.5から始まり、CNGは4.6.2から、
  • SHA512、管理対象は1.1から始まり、 Cng 3.5から。

ただし、フレームワークのバージョンに制約されない場合、またはレガシーOSバージョンをサポートする場合は、 CNGバージョンを使用する必要があると思います:

  • Cngで後置されたハッシュアルゴリズムは、 bcrypt
  • を使用する唯一のアルゴリズムです
  • 時間がかかる可能性があるという事実は、ブルートフォース攻撃から保護するため、実際には利点です。ユーザー側では300ミリ秒でも3ミリ秒でも違いはありませんが、攻撃者にとっては100桁です。
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top