c# - sha512cryptoserviceprovider - CNG, CryptoServiceProvider e implementaciones administradas de HashAlgorithm
sha512managed (3)
Así que me preguntaba si hay diferencias importantes entre las diversas implementaciones de los algoritmos hash, tome la serie de algoritmos SHA, por ejemplo. Todos ellos tienen 3 implementaciones cada uno, 1 en código administrado y 2 envoltorios alrededor de diferentes API criptográficas nativas, pero ¿hay alguna diferencia importante entre usar alguno de ellos? Me imagino que las versiones de envoltura podrían tener un mayor rendimiento ya que se ejecutan en código nativo, pero todos deben realizar exactamente los mismos cálculos y así proporcionar la misma salida, es decir, pueden intercambiarse. ¿Es esto correcto?
Por ejemplo, SHA512CNG no se puede usar en XP SP2 (los documentos son incorrectos) pero SHA512MANAGED puede hacerlo.
@Maxim - Gracias, pero no exactamente lo que estaba pidiendo. Me preguntaba si existe alguna diferencia, además del posible rendimiento, del uso de las implementaciones Managed / CryptoServiceProvider / CNG de un algoritmo hash dado. Con .NET 3.5 obtienes todos los algoritmos hash con tres implementaciones, por lo que
SHA512Managed SHA512CryptoServiceProvider SHA512Cng
Los dos últimos son envoltorios alrededor de API nativas. Esto es cierto para todas las implementaciones de SHAxxx, por ejemplo.
Una diferencia es que las versiones nativas (al menos algunas de ellas) están certificadas por FIPS (es decir, aprobadas por el gobierno de EE. UU.), Mientras que las administradas no lo están. Si su código se está ejecutando en un equipo con Windows que se ha configurado como "FIPS solamente", los intentos de usar las versiones administradas fallarán.
La mayoría de las máquinas con Windows no están configuradas de esa manera, pero si se está implementando en un entorno orientado a la administración o a la defensa (u otro entorno altamente seguro), es posible que se encuentre con esta situación.
Ver http://blogs.msdn.com/shawnfa/archive/2005/05/16/417975.aspx .
Se supone que las versiones de Cng son un poco más rápidas, pero acabo de escribir un pequeño programa que compara las velocidades de cada uno. (Tenía un cliente que preguntaba sobre las características de rendimiento de MD5 frente a SHA1)
Me sorprendió descubrir que hay poca o ninguna diferencia entre MD5 y SHA1, pero también me sorprendió que haya una ligera diferencia en Cng y CryptoServiceProvider.
La fuente es bastante directa, agregué representantes para hacer la misma iteración varias veces para poder promediar en caso de que hubiera alguna rareza, en mi máquina durante una de las carreras.
llame a lo siguiente con una llamada como esta:
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;
}
Ejecuté esto en un bucle de tamaño creciente para determinar si uno se caía cuando usaba entradas grandes o pequeñas. Aquí está el ciclo, y los datos siguen (mi computadora se quedó sin ram en 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
Hice una comparación rápida y sucia entre CNG
y managed
en SHA512, que es el algoritmo SHA más lento de todos los AFAIK que utiliza el código siguiente.
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());
}
Después de varias corridas, descubrí que la diferencia era que el CNG era considerablemente más rápido que la versión administrada del algoritmo, con aproximadamente 21.7% to 49.5%