2013-11-22 10 views
6

Ich schreibe eine Erweiterung Methode, die die Erstellung von Hashes durch Entfernen einer Tonne Boilerplate vereinfacht, ist mein Problem jedoch, dass, wenn ich durch den Code Schritt, immer wählt , ob oder nicht ich nenne SHA256.Create(), SHA256Cng.Create(), SHA256Managed.Create() oder SHA256CryptoServiceProvider.Create()Warum erscheinen alle Varianten von SHA256 als SHA256Managed?

es ist die gleiche Geschichte, wenn ich einen anderen Hash-Algorithmus wie MD5 holen, aber im Fall von MD5 es immer Picks MD5CryptoServiceProvider unabhängig von Klasse, die ich tatsächlich nutzen ...

Warum ich? s das?

Hier ist mein 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 
      } 
     } 
    } 
} 

Also, jede mögliche Hilfe?

+0

Es ist nicht besonders überraschend, (aber ich habe gedacht, es soll Warnungen werden erzeugt), da 'create' statisch auf die definiert ist' SHA256' Klasse, und die anderen Klassen erben von diesem, und so rufen Sie die gleiche Methode in jedem Fall. Die nicht abstrakten Klassen haben öffentliche Konstruktoren. –

+0

Also, was ist der Sinn von anderen Versionen der Klasse, wenn die create-Methode nicht ändert, was es tut? –

+0

Da die Instanzen dieser Klassen verschiedene Dinge tun. Sie sind nur für Ihren Anwendungsfall nicht relevant. – Mark

Antwort

10

Das liegt daran, dass Sie immer dieselbe statische Methode aufrufen, SHA256.Create. SHA256 ist eine abstrakte Klasse und ihre Nachkommen tun nicht bieten eine alternative Methode. In der Tat gibt Ihnen Resharper eine Warnung, dass Sie von einem abgeleiteten Typ auf ein statisches Element zugreifen.

Tatsächlich ist das Aufrufen von SHA256.Create dasselbe wie das Aufrufen von HashAlgorithm.Create. Beide Klassen rufen intern dieselbe Implementierung auf und geben das Ergebnis einfach an verschiedene Typen aus.

Die SHA256.Create Methode wird die Standardimplementierung erstellen, die in machine.config spezifiziert und kann in Ihrem app.config außer Kraft gesetzt werden

Wenn Sie einen bestimmten Anbieter verwenden möchten, SHA256.Create(string) verwenden Sie den Namen des Anbieters vorbei Sie Möchte benutzen.

Beispiele sind:

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

EDIT

Die Dokumentation von HashAlgorithm.Create eine Liste der gültigen Algorithmus Namen angibt. Der MSDN-Artikel Mapping Algorithm Names to Cryptography Classes beschreibt, wie Sie Algorithmus-Namen anderen Anbietern zuordnen können (eigene, von Drittanbietern, hardwarebeschleunigt oder was auch immer) und sie anstelle der Standardalgorithmen verwenden.

EDIT 2

Es ist auch möglich, die Zuordnungen programmatisch zu ändern. Also, zur Karte „Dog“ die SHA512CryptoServiceProvider, müssen Sie nur schreiben:

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

, aber ich benutze nicht sha256.create jedes Mal ... Ich benutze sha256Managed.create und sha256Cng.create für die anderen, und es gibt mir immer noch das gleiche Ergebnis ... –

+1

@ElectricCoffee - es gibt keine 'sha256Managed.Create 'method - aber' sha256Managed' * erbt * von 'Sha256' und so kann der Aufruf kompiliert werden. –

+0

Also was ist der Punkt? –