为什么SHA256的所有变体都显示为SHA256Managed?

Ele*_*fee 8 c# hash checksum md5 sha256

我正在编写一种扩展方法,通过删除大量的样板来简化哈希的创建,但问题是每当我单步执行代码时,无论是否调用,我都可以看到它总是选择,或者SHA256ManagedSHA256.Create()SHA256Cng.Create()SHA256Managed.Create()SHA256CryptoServiceProvider.Create()

当我选择不同的哈希算法(如MD5)时,情况也是如此,但在MD5的情况下,无论我实际使用哪个类,它都会选择MD5CryptoServiceProvider...

这是为什么?

这是我的代码:

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
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

那么,有什么帮助吗?

Pan*_*vos 13

那是因为你总是调用相同的静态方法SHA256.Create.SHA256是一个抽象类,它的后代提供替代方法.实际上,Resharper会向您发出警告,提示您正在从派生类型访问静态成员.

实际上,调用SHA256.Create与调用HashAlgorithm.Create相同.这两个类在内部调用相同的实现,并简单地将结果转换为不同的类型.

SHA256.Create方法将创建在machine.config中指定,并可以在你的app.config被重写默认的实现

如果要使用特定提供程序,请使用SHA256.Create(string)传递要使用的提供程序的名称.

例如:

SHA256.Create("System.Security.Cryptography.SHA256Cng");
HashAlgorithm.Create("System.Security.Cryptography.SHA256Cng");
SHA256.Create("System.Security.Cryptography.SHA256CryptoServiceProvider");
Run Code Online (Sandbox Code Playgroud)

编辑

HashAlgorithm.Create的文档指定了有效算法名称的列表.MSDN文章映射算法名称到密码术类描述了如何将算法名称映射到其他提供程序(您自己的,第三方,硬件加速或其他)并使用它们而不是默认算法.

编辑2

也可以通过编程方式更改映射.因此,要将"Dog"映射到SHA512CryptoServiceProvider,您只需要编写:

CryptoConfig.AddAlgorithm(
             typeof(System.Security.Cryptography.SHA512CryptoServiceProvider),
             "Dog");
var t4 = HashAlgorithm.Create("Dog");
Run Code Online (Sandbox Code Playgroud)

  • @ElectricCoffee - 没有`sha256Managed.Create`方法 - 但`sha256Managed`*从`Sha256`继承*,因此可以编译调用. (2认同)