2008-10-17 60 views
18

所以我想知道散列算法的各種實現之間是否存在任何主要差異,例如以SHA系列算法爲例。他們都有3個實現,每個都有1個託管代碼和2個包裝不同的本機加密API,但是在使用它們之間有什麼重大差異?我可以想象,包裝版本可以有更高的性能,因爲它是在本機代碼中執行的,但顯然嘿所有需要執行完全相同的計算,並因此提供相同的輸出,即嘿是可互換的。它是否正確?CNG,CryptoServiceProvider和HashAlgorithm的託管實現

例如SHA512CNG不能用於XP SP2(文檔錯誤),但SHA512MANAGED可以。


@Maxim - 謝謝,但不是我所要求的。我詢問使用給定散列算法的Managed/CryptoServiceProvider/CNG實現是否有任何區別,除了可能的性能之外。在.NET 3.5,你得到的所有的哈希算法有三個實現,所以

SHA512Managed SHA512CryptoServiceProvider SHA512Cng

各地的原生API後面兩種包裝。例如,所有SHAxxx實現都是如此。

+0

我有一次發現的原生包裝實施的一個(加密相當快,忘了這一個)在XP SP1與SP2中產生不同的結果。這是相當一段時間,當我使用.Net 1.1,因此我訴諸使用託管實現,而不是更「便攜」 – faulty 2008-10-20 12:28:38

回答

16

一個不同之處在於,本地版本(至少其中一些版本)經過FIPS認證(即由美國政府批准),而託管版本則不是。如果您的代碼碰巧在已配置爲「僅FIPS」的Windows計算機上運行,​​則嘗試使用受管版本將失敗。

大多數Windows機器沒有以這種方式配置,但如果你部署到政府 - 或防禦爲導向(或其他高安全性)環境中,你可能會遇到這種情況。

請參閱http://blogs.msdn.com/shawnfa/archive/2005/05/16/417975.aspx

4

壓縮天然氣版本應該是快一點,但我只是寫了一個小程序,每一個的速度進行比較。 (我有一個客戶詢問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 
1

我做了SHA512 CNGmanaged之間的快速和骯髒的比較是最慢的所有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%