What is the difference between using MD5.Create and MD5CryptoServiceProvider?
In the .NET framework there are a couple of ways to calcul开发者_运维技巧ate an MD5 hash it seems, however there is something I don't understand;
What is the distinction between the following? What sets them apart from eachother? They seem to produce identical results:
public static string GetMD5Hash(string str)
{
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
byte[] bytes = ASCIIEncoding.Default.GetBytes(str);
byte[] encoded = md5.ComputeHash(bytes);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < encoded.Length; i++)
sb.Append(encoded[i].ToString("x2"));
return sb.ToString();
}
public static string GetMD5Hash2(string str)
{
System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create();
byte[] bytes = Encoding.Default.GetBytes(str);
byte[] encoded = md5.ComputeHash(bytes);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < encoded.Length; i++)
sb.Append(encoded[i].ToString("x2"));
return sb.ToString();
}
System.Security.Cryptography.MD5.Create() is actually creating a MD5CryptoServiceProvider. That is why you see the same results.
Looking at the definition MD5 is the base class and it's abstract. I'm guessing they added the public create function for ease of use.
public sealed class MD5CryptoServiceProvider : MD5 { }
public abstract class MD5 : HashAlgorithm { }
Take a look at the definitions.
MD5 Represents the abstract class from which all implementations of the MD5 hash algorithm inherit.
MD5CryptoServiceProvider Computes the MD5 hash value for the input data using the implementation provided by the cryptographic service provider (CSP). This class cannot be inherited.
As Jason Rowe mentioned (please vote for his answer, this is just a word of warning), there is no functional difference. However, there is a difference if you are considering MD5Managed
(or any cryptography class with Managed
in the name). Managed
-named classes cannot be used when FIPS-compliant encryption algorithms are enabled via Group Policy.
You can also create a MD5CryptoServiceProvider object one of these ways:
(MD5CryptoServiceProvider) HashAlgorithm.Create("MD5");
(MD5CryptoServiceProvider) HashAlgorithm.Create("System.Security.Cryptography.MD5");
All MD5 classes return same hashes because MD5 is a standard algorithm not because their code is the same.
But the way to create a MD5CryptoServiceProvider object is not the only choice.
US government computers running Windows must have FIPS mode enabled. This mode ensures that cryptographic code used is NIST validated.
The various .NET cryptographic classes usually exist in several versions. One version uses pure .NET code while the others call a Win32 API cryptographic function.
The various Win32 cryptographic APIs are:
- Windows NT 4 cryptographic API: CAPI (CryptoAPI). My understanding is CSP (Cryptographic Service Provider) is a cryptographic API above the CryptoAPI.
- Windows Vista cryptographic API: CNG (Cryptography Next Generation)
Microsoft says Cryptographic Service Provider is deprecated and may be removed in future Windows versions and says CNG is the long-term replacement for the CryptoAPI.
The .NET cryptographic classes names usually have these suffixes:
- "CryptoServiceProvider" for the classes that call the CryptoAPI Win32 API.
- "Cng" for the classes that call the CNG Win32 API.
- "Managed" for the pure .NET code classes.
Some Win32 API may not be FIPS conformant and it seems that for an undisclosed reason Microsoft did not asked or could not obtain FIPS validation for cryptographic .NET pure code.
Classes that are not FIPS conformant rise a CryptographicException on computers that have FIPS mode enabled. This is mentioned in their documentation.
So, if your program is not intended to run on a US government PC you are free to use the fastest class.
About MD5, as classes names suggest, MD5CryptoServiceProvider class should call the very old and to be deprecated CryptoAPI and is FIPS conformant, while MD5Cng class calls the CNG API and is not FIPS conformant. This shows MD5 may not be usable on US government computers on future Windows versions. In fact, MD5 .NET classes documentation recommends replacing MD5 by SHA256 or SHA512.
For more on the ambiguous position of Microsoft about FIPS see:
https://blogs.technet.microsoft.com/secguide/2014/04/07/why-were-not-recommending-fips-mode-anymore/
MD5CryptoServiceProvider exists from .NET Framework 1.1. MD5CryptoServiceProvider class was added at Windows XP time. At that time the underlying Win32 CNG API did not exist. So MD5.Create method had no choice of algorithm and Microsoft probably did not yet plan to implement CNG on Windows. MD5Cng exists since .NET Framework 3.5, after CNG was added to Vista.
Approximative execution time compared to MD5CryptoServiceProvider (lower is better):
MD5Cng: x 1.08 (.NET Framework 3.5)
SHA256CryptoServiceProvider: x 2.5 (.NET Framework 3.5)
SHA256Cng: x 2.4 (.NET Framework 3.5)
SHA256Managed: x 4.8 (.NET Framework 1.1)
These unexpected results show SHA256Managed .NET pure code implementation is slower.
At the time SHA256Managed was implemented the better performing Windows Vista CNG did not exist.
Execution is always a little faster when performed on a Stream than on a byte array.
Hash for this post to verify it was not modified by a foreign agent:
1c84TiredWithMSDNwrittenByAncientEgyptians4cfebef40b0ae0a906b97c7
My 2 cents.
MD5
adds a little overhead and it is slower compared to MD5CryptoServiceProvider
I just ran a little stress test generating 300k hashes of a string:
MD5CryptoServiceProvider: 00:00:01.1750834
MD5: 00:00:01.6398959
Almost 1.5-times slower.
PS. Tested on an i7 core laptop
精彩评论