2013-11-22 21 views
6

Tôi đang viết một phương pháp mở rộng giúp đơn giản hoá việc tạo băm bằng cách xóa một tấn bản mẫu, tuy nhiên, vấn đề của tôi là bất cứ khi nào tôi bước qua mã, tôi có thể thấy rằng luôn luôn chọn SHA256Managed, bất kể có hay không tôi gọi SHA256.Create(), SHA256Cng.Create(), SHA256Managed.Create() hoặc SHA256CryptoServiceProvider.Create()Tại sao tất cả các biến thể của SHA256 xuất hiện dưới dạng SHA256Quản lý?

đó là những câu chuyện tương tự khi tôi chọn một thuật toán băm khác nhau như MD5, nhưng trong trường hợp của MD5 nó luôn chọn MD5CryptoServiceProvider bất kể lớp mà tôi thực sự sử dụng ...

Tại sao tôi đó?

Dưới đây là mã của tôi:

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 
      } 
     } 
    } 
} 

Vì vậy, bất kỳ sự giúp đỡ?

+0

Nó không đáng ngạc nhiên (nhưng tôi nghĩ là nên tạo cảnh báo) vì 'Create' được định nghĩa tĩnh trên' Lớp SHA256', và các lớp khác kế thừa từ đó, và vì vậy bạn đang gọi cùng một phương thức trong mỗi trường hợp. Các lớp không trừu tượng có các hàm tạo công khai. –

+0

Vì vậy, điểm của việc có các phiên bản khác của lớp là gì nếu phương thức tạo không thay đổi những gì nó đang làm? –

+0

Bởi vì các trường hợp của các lớp đó làm những việc khác nhau. Chúng không liên quan đến trường hợp sử dụng của bạn. – Mark

Trả lời

10

Đó là vì bạn luôn gọi cùng một phương thức tĩnh, SHA256.Create. SHA256 là một lớp trừu tượng và con cháu của nó làm không cung cấp một phương pháp thay thế. Trong thực tế, Resharper sẽ cho bạn một cảnh báo rằng bạn đang truy cập một thành viên tĩnh từ một kiểu có nguồn gốc.

Thực tế, gọi SHA256.Create giống như gọi HashAlgorithm.Create. Cả hai lớp đều gọi cùng một triển khai thực hiện nội bộ và chỉ cần đưa kết quả vào các kiểu khác nhau.

Các SHA256.Create phương pháp sẽ tạo ra việc thực hiện mặc định được quy định tại Machine.config và có thể được overriden trong app.config của bạn

Nếu bạn muốn sử dụng một nhà cung cấp cụ thể, sử dụng SHA256.Create(string) qua tên của nhà cung cấp bạn muốn sử dụng.

Ví dụ:

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

EDIT

Các tài liệu của HashAlgorithm.Create xác định một danh sách tên thuật toán hợp lệ. Bài viết MS2 Mapping Algorithm Names to Cryptography Classes mô tả cách bạn có thể ánh xạ tên thuật toán cho các nhà cung cấp khác (của riêng bạn, của bên thứ ba, tăng tốc phần cứng hoặc bất kỳ thứ gì) và sử dụng chúng thay vì các thuật toán mặc định.

EDIT 2

Nó cũng có thể thay đổi ánh xạ theo chương trình. Vì vậy, để lập bản đồ "Dog" cho SHA512CryptoServiceProvider, bạn chỉ cần viết:

CryptoConfig.AddAlgorithm(
      typeof(System.Security.Cryptography.SHA512CryptoServiceProvider), 
      "Dog"); 
var t4 = HashAlgorithm.Create("Dog"); 
+0

nhưng tôi không sử dụng sha256.create mỗi lần ... Tôi sử dụng sha256Managed.create và sha256Cng.create cho những người khác, và nó vẫn mang lại cho tôi kết quả tương tự ... –

+1

@ElectricCoffee - không có 'sha256Managed.Create 'phương thức - nhưng' sha256Quản lý' * kế thừa * từ 'Sha256' và do đó cuộc gọi có thể được biên dịch. –

+0

vậy điểm là gì? –

Các vấn đề liên quan