Подтвердить что ты не робот

CNG, CryptoServiceProvider и управляемые реализации HashAlgorithm

Итак, мне было интересно, существуют ли какие-либо существенные различия между различными реализациями хэш-алгоритмов, например, возьмите серию алгоритмов SHA. Все они имеют по 3 реализации каждый, 1 в управляемом коде и 2 обертки вокруг разных API-интерфейсов crypto, но есть ли какие-либо существенные различия между использованием любого из них? Я могу представить, что версии обертки могут иметь более высокую производительность с момента ее выполнения в собственном коде, но все же нужно выполнять точные вычисления и, таким образом, обеспечивать тот же результат, т.е. Они взаимозаменяемы. Правильно ли это?

Например, SHA512CNG не может использоваться на XP SP2 (документы ошибочны), но SHA512MANAGED может.


@Maxim - Спасибо, но не совсем то, о чем я просил. Я спрашивал, есть ли какая-либо разница, отличная от производительности, от использования реализаций Managed/CryptoServiceProvider/CNG данного хеш-алгоритма. С .NET 3.5 вы получаете все хэш-алгоритмы с тремя реализациями, поэтому

SHA512Managed SHA512CryptoServiceProvider SHA512Cng

Последние два являются обертками вокруг собственных API. Это справедливо для всех реализаций SHAxxx, например.

4b9b3361

Ответ 1

Одно из отличий заключается в том, что родные версии (по крайней мере некоторые из них) сертифицированы FIPS (т.е. одобрены правительством США), тогда как управляемые - нет. Если ваш код работает на компьютере под управлением Windows, который был настроен как "Только FIPS", попытки использовать управляемые версии не удастся.

Большинство машин Windows не настроены таким образом, но если вы развертываете среду, ориентированную на правительство или защиту (или другую высоко защищенную), вы можете столкнуться с этой ситуацией.

См. http://blogs.msdn.com/shawnfa/archive/2005/05/16/417975.aspx.

Ответ 2

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):

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

Ответ 3

Я сделал быстрое и грязное сравнение между CNG и managed на SHA512, которое является самым медленным из всех алгоритмов SHA AFAIK, используя следующий код.

    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% to 49.5%