24

所以我想知道哈希算法的各种实现之间是否有任何重大差异,以SHA系列算法为例。它们每个都有 3 个实现,1 个在托管代码中,2 个围绕不同的本机加密 API 进行包装,但是使用它们之间有什么主要区别吗?我可以想象包装器版本可以具有更高的性能,因为它是在本机代码中执行的,但是 surley 嘿都需要执行完全相同的计算并因此提供相同的输出,即它们是可互换的。它是否正确?

例如 SHA512CNG 不能在 XP SP2 上使用(文档错误),但 SHA512MANAGED 可以。


@Maxim - 谢谢,但不是我所要求的。我在问使用给定哈希算法的 Managed/CryptoServiceProvider/CNG 实现是否有任何区别,除了可能的性能。使用 .NET 3.5,您可以获得具有三种实现的所有哈希算法,所以

SHA512Managed SHA512CryptoServiceProvider SHA512Cng

后两者是原生 API 的包装器。例如,所有 SHAxxx 实现都是如此。

4

4 回答 4

18

一个区别是本机版本(至少其中一些)经过 FIPS 认证(即,由美国政府批准),而托管版本则不是。如果您的代码恰好在已配置为“仅 FIPS”的 Windows 计算机上运行,​​则尝试使用托管版本将失败。

大多数 Windows 机器不是以这种方式配置的,但如果您要部署到政府或国防(或其他高度安全)环境,您可能会遇到这种情况。

请参阅http://blogs.msdn.com/shawnfa/archive/2005/05/16/417975.aspx

于 2008-11-12T21:03:22.947 回答
4

Cng 版本应该会快一点,但我只是写了一个小程序来比较每个版本的速度。(我有一个客户询问 MD5 与 SHA1 的性能特征)

我很惊讶地发现 MD5 和 SHA1 之间几乎没有区别,但也很惊讶 Cng 和 CryptoServiceProvider 之间存在细微差别。

The source is pretty straight forward, I added reps to do the same iteration multiple times so I could average in case there was any weirdness going on, on my machine during one of the runs.

call the following with a call like this:

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;
    }

I ran this in a loop of increasing size to figure out if one fell over when using large or small inputs. Here is the loop, and the data follows (my computer ran out of ram at 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
于 2009-06-16T21:48:21.780 回答
1

I did a quick and dirty comparison between CNG and managed on SHA512 which is the slowest of all SHA algorithms AFAIK using the code below.

    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());
    }

After several runs I found that the difference was that CNG was considerably faster than managed version of the algorithm with about 21.7% to 49.5%

于 2016-09-21T11:18:51.677 回答
1

Another difference between the Managed and the CNG versions is the supported .Net Framework version: e.g.

  • the AES Managed version starts from 3.5, while the CNG from 4.6.2 and for
  • SHA512, Managed starts from 1.1 and Cng from 3.5.

However, I believe that if we are not constrained by the framework version or to support legacy OS versions, we should use the CNG versions:

  • The hashing algorithms postfixed with Cng are the only ones that use bcrypt
  • The fact that it might take longer is actually an advantage as it protects from brute force attacks: on the user side 300ms or 3ms makes no difference, while for an attacker it is an order 100 magnitude!
于 2018-08-29T10:08:03.913 回答