The Slow Adoption of Cryptography in .NET

--

And, so, .NET 9.0 preview is here, and it’s all a bit of a disappointment. While other companies, such as Google and Cloudflare have really push forward in adopting the latest (and best) cryptography methods, Microsoft have been slow to adopt.

I may be wrong, but Microsoft often takes a long time to adopt the most up-to-date cryptography. While OpenSSL is also fairly slow, Microsoft seems to take an even longer time to advance its libraries for cryptography. This happened for ECC, and where it took years for them to do the most basic basic elliptic curves, and to integrate the ECDSA digital signature method. And, so, with .NET 8, we saw them adding SHA3 [here]:

In 2014, NIST defined that SHA-3 would be based on the Keccak method, and then in 2015, it published the standard. Many applications now use SHA-3, but it has been missing from Microsoft’s .NET framework. Now, Microsoft say it has been added to .NET 8, and so we can try:

namespace SHA3
{
class Program
{
static void Main(string[] args)
{
var password="qwerty";


try {
if (args.Length >0) password=args[0];

byte[] hash1 = System.Security.Cryptography.SHA3_256.HashData(System.Text.Encoding.UTF8.GetBytes(password));
byte[] hash2 = System.Security.Cryptography.SHA3_384.HashData(System.Text.Encoding.UTF8.GetBytes(password));
byte[] hash3 = System.Security.Cryptography.SHA3_512.HashData(System.Text.Encoding.UTF8.GetBytes(password));

Console.WriteLine("Message: {0}",password);

Console.WriteLine("\nSHA3 (256): {0} [{1}]",Convert.ToBase64String(hash1),Convert.ToHexString(hash1));
Console.WriteLine("\nSHA3 (384): {0} [{1}]",Convert.ToBase64String(hash2),Convert.ToHexString(hash2));
Console.WriteLine("\nSHA3 (512): {0} [{1}]",Convert.ToBase64String(hash3),Convert.ToHexString(hash3));
} catch (Exception e) {
Console.WriteLine("Error: {0}",e.Message);
}
}
}
}

Unforunately, on the platform I compile it on, give me an error of “Error: Operation is not supported on this platform.”:

I really can’t understand why this happens, as the computation is fairly easy to implement:

  • SHA-3, Keccak and SHAKE . SHA-3. Implements SHA-3, Keccak and SHAKE (SHA-3 winner).
  • SHA-3. SHA-3. SHA-3 was known as Keccak and is a hash function designed by Guido Bertoni, Joan Daemen, Michaël Peeters, and Gilles Van Assche.
  • cSHAKE. cSHAKE. An eXtendable-Output Function (XOF) produces a bit string that can be of any length.
  • Keccak, SHAKE, cSHAKE and KMAC. cSHAKE. This implements Keccak, SHAKE, cSHAKE and KMAC in Node.js.

If we try the OpenSSL version on the machine we see that it is 3.0.0:

PS C:\python3\dotnet\chacha20> openssl version
OpenSSL 3.0.0 7 sep 2021 (Library: OpenSSL 3.0.0 7 sep 2021)

and where SHA-3 should be supported:

PS C:\python3\dotnet\chacha20> openssl list -digest-algorithms
Legacy:
RSA-MD4 => MD4
RSA-MD5 => MD5
RSA-MDC2 => MDC2
RSA-RIPEMD160 => RIPEMD160
RSA-SHA1 => SHA1
RSA-SHA1-2 => RSA-SHA1
RSA-SHA224 => SHA224
RSA-SHA256 => SHA256
RSA-SHA3-224 => SHA3-224
RSA-SHA3-256 => SHA3-256
RSA-SHA3-384 => SHA3-384
RSA-SHA3-512 => SHA3-512
RSA-SHA384 => SHA384
RSA-SHA512 => SHA512
RSA-SHA512/224 => SHA512-224
RSA-SHA512/256 => SHA512-256
RSA-SM3 => SM3
BLAKE2b512
BLAKE2s256
id-rsassa-pkcs1-v1_5-with-sha3-224 => SHA3-224
id-rsassa-pkcs1-v1_5-with-sha3-256 => SHA3-256
id-rsassa-pkcs1-v1_5-with-sha3-384 => SHA3-384
id-rsassa-pkcs1-v1_5-with-sha3-512 => SHA3-512
MD4
md4WithRSAEncryption => MD4
MD5
MD5-SHA1
md5WithRSAEncryption => MD5
MDC2
mdc2WithRSA => MDC2
ripemd => RIPEMD160
RIPEMD160
ripemd160WithRSA => RIPEMD160
rmd160 => RIPEMD160
SHA1
sha1WithRSAEncryption => SHA1
SHA224
sha224WithRSAEncryption => SHA224
SHA256
sha256WithRSAEncryption => SHA256
SHA3-224
SHA3-256
SHA3-384
SHA3-512
SHA384
sha384WithRSAEncryption => SHA384
SHA512
SHA512-224
sha512-224WithRSAEncryption => SHA512-224
SHA512-256
sha512-256WithRSAEncryption => SHA512-256
sha512WithRSAEncryption => SHA512
SHAKE128
SHAKE256
SM3
sm3WithRSAEncryption => SM3
ssl3-md5 => MD5
ssl3-sha1 => SHA1
whirlpool
Provided:
{ 2.16.840.1.101.3.4.2.10, SHA3-512 } @ default
{ 1.2.156.10197.1.401, SM3 } @ default
{ 1.3.6.1.4.1.1722.12.2.2.8, BLAKE2S-256, BLAKE2s256 } @ default
{ 2.16.840.1.101.3.4.2.8, SHA3-256 } @ default
{ 2.16.840.1.101.3.4.2.7, SHA3-224 } @ default
{ 2.16.840.1.101.3.4.2.2, SHA-384, SHA2-384, SHA384 } @ default
{ 2.16.840.1.101.3.4.2.3, SHA-512, SHA2-512, SHA512 } @ default
{ 2.16.840.1.101.3.4.2.5, SHA-512/224, SHA2-512/224, SHA512-224 } @ default
{ 2.16.840.1.101.3.4.2.12, SHAKE-256, SHAKE256 } @ default
{ 2.16.840.1.101.3.4.2.1, SHA-256, SHA2-256, SHA256 } @ default
{ 1.3.14.3.2.26, SHA-1, SHA1, SSL3-SHA1 } @ default
{ 2.16.840.1.101.3.4.2.9, SHA3-384 } @ default
{ 2.16.840.1.101.3.4.2.11, SHAKE-128, SHAKE128 } @ default
MD5-SHA1 @ default
{ 1.2.840.113549.2.5, MD5, SSL3-MD5 } @ default
{ 2.16.840.1.101.3.4.2.4, SHA-224, SHA2-224, SHA224 } @ default
{ 1.3.6.1.4.1.1722.12.2.1.16, BLAKE2B-512, BLAKE2b512 } @ default
{ 2.16.840.1.101.3.4.2.6, SHA-512/256, SHA2-512/256, SHA512-256 } @ default
{ KECCAK-KMAC-128, KECCAK-KMAC128 } @ default
{ KECCAK-KMAC-256, KECCAK-KMAC256 } @ default

And, what about ChaCha20? Is that supported? Well, it should have been supported since .NET 5, but we get an exception of “Error: Algorithm ‘ChaCha20Poly1305’ is not supported on this platform”:

and where the message is:

PS C:\python3\dotnet\chacha20> dotnet run
Error: Algorithm 'ChaCha20Poly1305' is not supported on this platform.

Implementing SHA-3 in .NET

So, let’s just install an implementation with [here]:

dotnet add package SHA3.Net --version 2.0.0

The following is an outline of the code [here]:

namespace SafePrimes
{
using System;
using System.Diagnostics;
using SHA3.Net;
using System.Text;

// dotnet add package SHA3.Net --version 2.0.0

class Program
{







static void Main(string[] args)
{
var msg="Hello";
if (args.Length >0) msg=args[0];

try {
Console.WriteLine("Message: {0}",msg);

var hash1 = Sha3.Sha3224().ComputeHash(Encoding.ASCII.GetBytes(msg));
var hash2 = Sha3.Sha3256().ComputeHash(Encoding.ASCII.GetBytes(msg));
var hash3 = Sha3.Sha3384().ComputeHash(Encoding.ASCII.GetBytes(msg));
var hash4 = Sha3.Sha3512().ComputeHash(Encoding.ASCII.GetBytes(msg));
Console.WriteLine("SHA3-224 {0}",Convert.ToHexString(hash1));
Console.WriteLine("SHA3-256 {0}",Convert.ToHexString(hash2));
Console.WriteLine("SHA3-384 {0}",Convert.ToHexString(hash3));
Console.WriteLine("SHA3-512 {0}",Convert.ToHexString(hash4));


} catch (Exception e) {
Console.WriteLine("Error: {0}",e.Message);
}
}
}



}

and a sample run [here]:

Message: abc
SHA3-224 E642824C3F8CF24AD09234EE7D3C766FC9A3A5168D0C94AD73B46FDF
SHA3-256 3A985DA74FE225B2045C172D6BD390BD855F086E3E9D525B46BFE24511431532
SHA3-384 EC01498288516FC926459F58E2C6AD8DF9B473CB0FC08C2596DA7CF0E49BE4B298D88CEA927AC7F539F1EDF228376D25
SHA3-512 B751850B1A57168A5693CD924B6B096E08F621827444F70D884F5D0240D2712E10E116E9192AF3C91A7EC57647E3934057340B4CF408D5A56592F8274EEC53F0

Conclusions

I don’t understand why I get an error for the implement on the platform I am running SHA-3 on — as the implementation does not depend on any special hardware or software. The same goes for ChaCha20. For Microsoft, it’s just another disappointing implementation of cryptography.

Of course, a good part of this is that Microsoft is using OpenSSL was their core integration for cryptography, and also their aim to be FIPS complaint. But, you would think that a company like Microsoft would be able to write their own native code for this.

Here are some .NET/C# implementations:

https://asecuritysite.com/csharp/

and some PowerShell:

https://asecuritysite.com/powershell/

--

--

Prof Bill Buchanan OBE FRSE
ASecuritySite: When Bob Met Alice

Professor of Cryptography. Serial innovator. Believer in fairness, justice & freedom. Based in Edinburgh. Old World Breaker. New World Creator. Building trust.