Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do all the variants of SHA256 appear as SHA256Managed?

I'm writing an extension method that simplifies the creation of hashes by removing a ton of boilerplate, my problem is however that whenever I step through the code, I can see that it always picks SHA256Managed, regardless of whether or not I call SHA256.Create(), SHA256Cng.Create(), SHA256Managed.Create() or SHA256CryptoServiceProvider.Create()

It's the same story when I pick a different hashing algorithm like MD5, but in the case of MD5 it always picks MD5CryptoServiceProvider regardless of class that I actually use...

Why is that?

Here's my code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Utility.Methods
{
    public enum HashType { MD5, SHA512, SHA256, SHA384, SHA1 }
    public enum HashSubType {Normal, Cng, Managed, CryptoServiceProvider}

    public static class TextHasher
    {
        public static string Hash(this string input, HashType hash, HashSubType subType = HashSubType.Normal)
        {
            Func<HashAlgorithm, string> hashFunction = alg => HashingHelper(input, alg);

            switch (subType)
            {
                case HashSubType.Normal:
                    return hashFunction(NormalHashes(hash));
                case HashSubType.Cng:
                    return hashFunction(CngHashes(hash));
                case HashSubType.Managed:
                    return hashFunction(ManagedHashes(hash));
                case HashSubType.CryptoServiceProvider:
                    return hashFunction(CSPHashes(hash));
                default: return "error"; // unreachable
            }
        }

        private static string HashingHelper(string text, HashAlgorithm algorithm)
        {
            Func<string, byte[]> getHash = input => algorithm.ComputeHash(Encoding.UTF8.GetBytes(input));

            var sb = new StringBuilder();
            Array.ForEach(getHash(text), b => sb.Append(b.ToString("X")));

            return sb.ToString();
        }

        private static HashAlgorithm NormalHashes(HashType hash)
        {
            switch (hash)
            {
                case HashType.MD5:
                    return MD5.Create();
                case HashType.SHA1:
                    return SHA1.Create();
                case HashType.SHA256:
                    return SHA256.Create();
                case HashType.SHA384:
                    return SHA384.Create();
                case HashType.SHA512:
                    return SHA512.Create();
                default: return null; // unreachable
            }
        }

        private static HashAlgorithm CngHashes(HashType hash)
        {
            switch (hash)
            {
                case HashType.MD5:
                    return MD5Cng.Create();
                case HashType.SHA1:
                    return SHA1Cng.Create();
                case HashType.SHA256:
                    return SHA256Cng.Create();
                case HashType.SHA384:
                    return SHA384Cng.Create();
                case HashType.SHA512:
                    return SHA512Cng.Create();
                default: return null; // unreachable
            }
        }

        private static HashAlgorithm ManagedHashes(HashType hash)
        {
            switch (hash)
            {
                case HashType.SHA1:
                    return SHA1Managed.Create();
                case HashType.SHA256:
                    return SHA256Managed.Create();
                case HashType.SHA384:
                    return SHA384Managed.Create();
                case HashType.SHA512:
                    return SHA512Managed.Create();
                default: return null; // unreachable
            }
        }

        private static HashAlgorithm CSPHashes(HashType hash)
        {
            switch (hash)
            {
                case HashType.MD5:
                    return MD5CryptoServiceProvider.Create();
                case HashType.SHA1:
                    return SHA1CryptoServiceProvider.Create();
                case HashType.SHA256:
                    return SHA256CryptoServiceProvider.Create();
                case HashType.SHA384:
                    return SHA384CryptoServiceProvider.Create();
                case HashType.SHA512:
                    return SHA512CryptoServiceProvider.Create();
                default: return null; // unreachable
            }
        }
    }
}

So, any help?

like image 865
Electric Coffee Avatar asked Nov 22 '13 10:11

Electric Coffee


People also ask

What is sha256managed?

The secure hash algorithm with a digest size of 256 bits, or the SHA 256 algorithm, is one of the most widely used hash algorithms. While there are other variants, SHA 256 has been at the forefront of real-world applications.

How many characters are in SHA256 hash?

It's always 64 characters, which can be determined by running anything into one of the online SHA-256 calculators.

How secure is SHA 256?

Three properties make SHA-256 this secure. First, it is almost impossible to reconstruct the initial data from the hash value. A brute-force attack would need to make 2256 attempts to generate the initial data. Second, having two messages with the same hash value (called a collision) is extremely unlikely.

What is SHA256 in C#?

The HashAlgorithm class is the base class for hash algorithms including MD5, RIPEMD160, SHA1, SHA256, SHA384, and SHA512. The ComputeHash method of HashAlgorithm computes a hash. It takes a byte array or stream as an input and returns a hash in the form of a byte array of 256 bits. byte[] bytes = sha256Hash.


1 Answers

That's because you are always calling the same static method, SHA256.Create. SHA256 is an abstract class and its descendants do not provide an alternate method. In fact, Resharper will give you a warning that you are accessing a static member from a derived type.

In fact, calling SHA256.Create is the same as calling HashAlgorithm.Create. Both classes call the same implementation internally and simply cast the result to different types.

The SHA256.Create method will create the default implementation that is specified in machine.config and can be overriden in your app.config

If you want to use a specific provider, use SHA256.Create(string) passing the name of the provider you want to use.

Examples are:

SHA256.Create("System.Security.Cryptography.SHA256Cng");
HashAlgorithm.Create("System.Security.Cryptography.SHA256Cng");
SHA256.Create("System.Security.Cryptography.SHA256CryptoServiceProvider");

EDIT

The documentation of HashAlgorithm.Create specifies a list of valid algorithm names. The MSDN article Mapping Algorithm Names to Cryptography Classes describes how you can map algorithm names to other providers (your own, third-party, hardware-accelerated or whatever) and use them instead of the default algorithms.

EDIT 2

It is also possible to change the mappings programmatically. So, to map "Dog" to the SHA512CryptoServiceProvider, you just need to write:

CryptoConfig.AddAlgorithm(
             typeof(System.Security.Cryptography.SHA512CryptoServiceProvider),
             "Dog");
var t4 = HashAlgorithm.Create("Dog");
like image 69
Panagiotis Kanavos Avatar answered Sep 30 '22 16:09

Panagiotis Kanavos