2013-11-22 1 views
6

많은 상용구를 제거하여 해시 생성을 단순화하는 확장 방법을 쓰고 있습니다. 그러나 코드를 단계별로 실행할 때마다 항상을 선택합니다. 여부에 관계없이 SHA256Managed을 선택합니다. 나는 SHA256.Create(), SHA256Cng.Create(), SHA256Managed.Create() 또는SHA256의 모든 변형이 SHA256Managed로 나타나는 이유는 무엇입니까?

내가 MD5와 같은 다른 해싱 알고리즘을 선택할 때이 같은 이야기 SHA256CryptoServiceProvider.Create()하지만, 전화를 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 
      } 
     } 
    } 
} 

, 어떤 도움?

+0

그것은 (그러나 나는이 경고를 생성해야한다 생각했을 것) 특히 놀라운 일이 아니다은' SHA256' 클래스를 사용하고 다른 클래스는이를 상속하므로 각 경우에 동일한 메소드를 호출합니다. 비 추상 클래스에는 public 생성자가 있습니다. –

+0

그래서 create 메소드가 수행중인 작업을 변경하지 않으면 다른 버전의 클래스를 갖는 것이 무엇입니까? –

+0

이러한 클래스의 인스턴스는 다른 일을하기 때문에. 그것들은 당신의 유스 케이스와 관련이 없다. – Mark

답변

10

항상 동일한 정적 메서드 인 SHA256.Create을 호출하기 때문입니다. SHA256은 추상 클래스이며 그 자손은 이 아니라 대체 방법을 제공합니다. 사실, Resharper는 파생 된 유형의 정적 멤버에 액세스하고 있다는 경고를 제공합니다.

실제로 SHA256.Create를 호출하는 것은 HashAlgorithm.Create을 호출하는 것과 같습니다. 두 클래스 모두 내부적으로 동일한 구현을 호출하고 결과를 다른 유형으로 간단하게 캐스팅합니다.

의 machine.config에 지정되고 특정 공급자를 사용하려는 경우, 공급자의 이름을 통과 SHA256.Create(string)를 사용

당신의 app.config에서 오버라이드 (override) 할 수있는 기본 구현을 만들 것입니다 SHA256.Create 방법 당신 사용하고 싶다.

예는 다음과 같다 HashAlgorithm.Create 문서는 유효 알고리즘 이름의 목록을 지정

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

EDIT. MSDN 문서 Mapping Algorithm Names to Cryptography Classes은 알고리즘 이름을 다른 공급자 (자신, 제 3 자, 하드웨어 가속기 등)에 매핑하고 기본 알고리즘 대신 알고리즘 이름을 사용할 수있는 방법을 설명합니다.

프로그래밍 방식 매핑을 변경하는 것도 가능하다 (2)

EDIT. 그래서, SHA512CryptoServiceProvider에 "개"를 매핑, 당신은 쓸 필요가 : Create` 정적에 정의`이후

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

하지만 매번 sha256.create를 사용하지 않습니다 ... 저는 sha256Managed.create와 sha256Cng.create를 사용합니다. 여전히 동일한 결과를줍니다 ... –

+1

@ElectricCoffee - sha256Managed.Create가 없습니다 '메소드를 호출하지만'sha256Managed' *는'Sha256'으로부터 상속받습니다. 그래서 호출을 컴파일 할 수 있습니다. –

+0

그래서 요점은 무엇입니까? –

관련 문제