C# · 12月 23, 2021

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

我正在编写一个扩展方法,通过删除大量的样板来简化哈希的创建,但问题是每当我单步执行代码时,我都会看到它总是选择SHA256Managed,无论我是否调用SHA256. 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 } } }}

那么,有什么帮助吗?

解决方法 那是因为你总是调用相同的静态方法 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”);

编辑

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

编辑2

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

CryptoConfig.AddAlgorithm( typeof(System.Security.Cryptography.SHA512CryptoServiceProvider),”Dog”);var t4 = HashAlgorithm.Create(“Dog”);