The other day I was watching .NET cryptography tutorials on pluralsight (http://pluralsight.com/training/Courses/TableOfContents/cryptography-introduction-dotnet) and one thing struck me – there were some performance tests for SHA hash algorithms, the results of which were couter-intuitive. Namely – the SHA512 was faster than SHA256. I’m not an expert in cryptography, but i know a thing or two how SHA works and I could see nothing that could justify those results. So I did some testing
The result of 1000 hashings of 10 KB file on my PC:
SHA 256 – 202 ms.
SHA 512 – 955 ms.
Now that’s not what I’ve seen in the video ! I ran the ILSpy (http://ilspy.net/) on the libraries and a thing that immediately stands out as a difference between SHA256 and SHA512 (note: I was using System.Security.Cryptography.SHA256Managed, there is another flavor of SHA256 and I’ll talk about that later) is that where SHA256 uses int, SHA512 uses ulong.
Aha! I quickly recompiled everything as x64 and as expected the results were mighty different:
SHA 256 – 201 ms.
SHA 512 – 130 ms.
Now it makes sense. I guess historically framework designers thought that by the time SHA512 will be a standard, all compilations will be x64 bit so it made sense to speed it up for those kinds of builds.
One other interesting thing is that there are two (at least) mechanisms for SHA computation in .NET. The *Managed one (SHA1Managed, SHA512Managed,etc.) is older and it is not certified to be FIPS 140-2 compliant (which basically means it’s potentialy less secure and you definitely shouldn’t use it if you’re writing software for government/military or public safety use). The other option is to use CryptoServiceProviders (SHA512CryptoServiceProvider, SHA256CryptoServiceProvider, etc.). It’s altogether a better option because compliance aside, those algorithms are faster as they use native windows libraries instead of managed implementations (The only drawback is that you need framework 3.5+).
Here are all the results for different providers and different systems.
|x86||202 ms.||955 ms.||150 ms.||256 ms.|
|x64||201 ms.||130 ms.||114 ms.||73 ms.|
So, the bottom line – use CryptoServiceProvider wherever possible and get ready to move on to 64 bit compilation if you need that extra security and/or extra performance (there is about a gazilion reasons to do it anyway)