2012-04-20 14 views
15

Ich versuche eine portable Klassenbibliothek zu erstellen, die OAuth-URLs für andere Klassen/Anwendungen generiert. Diese Klassenbibliothek, die OAuth verwendet, muss eine portable Klassenbibliothek sein, damit sie mit verschiedenen Versionen einer von mir erstellten DropBox-API funktionieren kann.SHA1-Hash in der Portable-Klassenbibliothek generieren

Ein Teil dieser Klasse muss einen SHA1-Hash generieren, um die oauth_signature mit zu generieren.

Ich bin mir bewusst, dass die portable Klassenbibliothek System.Security.Cryptography nicht unterstützt. Gibt es also trotzdem, dass diese Klasse einen SHA1-Hash ohne diese Klasse generieren kann?

+2

Sie über einige Code aus Mono.Security kopieren könnte. – CodesInChaos

+2

Ich sehe keine problematischen Abhängigkeiten in der SHA1Managed-Klasse. Portable erscheint mir immer unfertig, wenn ich nachschaue. –

+0

Das wäre ein Problem, aber es ist eine ziemlich einfache String-Building-Klasse mit ein paar Methoden, so lange sie ihre Arbeit tun, ist unfertig kein Problem. –

Antwort

6

Mono bietet eine managed implementation of SHA1 für seine eigene mscorlib.dll (aber es ist nicht in Mono.Security.dll wie @CodeInChaos vorgeschlagen).

Es ist Open Source, sehr gut getestet und genau wie Microsoft-Implementierung verhalten soll (z es leitet sich von SHA1, HashAlgorith ... ICryptoTransform implementiert ...) so sollte es eine einfache Drop-in-Ersatz sein.

+0

Könntest du mir helfen, es einfach zu verwenden, um eine Zeichenfolge zu hashen? Der Code hat praktisch keinen Kommentar dazu, daher fällt es mir schwer zu verstehen. –

+1

Sie müssen die Zeichenfolge in Bytes umwandeln, z. 'System.Text.XXXEncoding.GetBytes()'. Seien Sie sehr vorsichtig mit Codierungen (z. B. UTF8 ist viel besser als ASCII), da unterschiedliche Bytes unterschiedliche Hashwerte ergeben. – poupou

+0

Ich weiß nicht, wie man das benutzt. Jemand kann mir helfen, einen SHA1-Hash aus einer Zeichenfolge zu generieren? – alvaropaco

2

Die SHA-1 Wikipedia article enthält Pseudocode, den Sie als Richtlinie für Ihre eigene Implementierung verwenden können. Aber wie immer bei kryptografischen Funktionen rate ich dringend zu einer bewährten Implementierung.

Angenommen, Sie möchten eine SHA-256-Implementierung, finden Sie eine in BouncyCastle, die im Quellcodeformat verfügbar ist. Die entsprechende Klasse heißt Org.BouncyCastle.Crypto.Digests.Sha256Digest (hier ist source).

8

Nun brauchte ich das auch vor kurzem, und ich fand viel einfacher SHA1 Implementierung von hashlib zu nehmen: http://hashlib.codeplex.com/

Mono Implementierung haben einige weit gehende Abhängigkeiten (Lokalisierung von Ausnahmen, etc.), während von hashlib müssen Sie nur um einige Dateien zu kopieren, ohne irgendwelche Änderungen daran vorzunehmen:

Converters.cs 
Hash.cs 
HashBuffer.cs 
HashCryptoNotBuildIn.cs 
HashResult.cs 
IHash.cs 
SHA0.cs 
SHA1.cs 

55 KB Code insgesamt, also nichts zu schwer.

+0

Arbeitete für mich. Ich musste jedoch einige zusätzliche Dateien zu Ihrer Liste hinzufügen. IHashInfo.cs (nicht alles wurde benötigt). ArrayExtentions.cs wurde auch für die Erweiterungsmethode .SubArray() benötigt, die in einer der oben genannten Klassen verwendet wird. Die HashFactory-Klasse wurde verkleinert, um den portierten Klassen zu entsprechen - aber sie erledigt die Aufgabe. Danke für die Hinweise. Ursprünglich drehte sich mein Kopf und betrachtete alle Klassen. Ihre Liste hat wirklich geholfen. – TravisWhidden

+0

Das funktioniert ganz gut, danke! Wie erwähnt, fehlt IHashInfo.cs in Ihrer Liste. Da ich nur eine Zeichenfolge zur SHA1-Konvertierung benötigte, konnte ich die Codegröße auf ~ 26 KB verkleinern. –

16

Ich denke, der einfachste Weg ist, das PCLCrypto nuget Paket zu verwenden. Dann können Sie tun:

private static string CalculateSha1Hash(string input) 
{ 
     // step 1, calculate MD5 hash from input 
     var hasher = WinRTCrypto.HashAlgorithmProvider.OpenAlgorithm(HashAlgorithm.Sha1); 
     byte[] inputBytes = Encoding.UTF8.GetBytes(input); 
     byte[] hash = hasher.HashData(inputBytes); 

     StringBuilder sb = new StringBuilder(); 
     for (int i = 0; i < hash.Length; i++) 
     { 
      sb.Append(hash[i].ToString("X2")); 
     } 
     return sb.ToString(); 
} 
+1

Ich stimme zu - aber Sie können das Beispiel ändern, um einen verwendeten Schlüssel anzuzeigen: byte [] keyMaterial; Byte [] Daten; var algorithm = WinRTCrypto.MacAlgorithmProvider.OpenAlgorithm (MacAlgorithm.HmacSha1); CryptographicHash hasher = algorithm.CreateHash (SchlüsselMaterial); hasher.Append (Daten); byte [] mac = hasher.GetValueAndReset(); Zeichenfolge macBase64 = Convert.ToBase64String (mac); –

+0

Großartiges Beispiel! Ich habe eine kleine Zugabe. Hex-String stattdessen in einer Zeile erstellen 5: return string.Join ("", hash.Select (b => b.ToString ("x2")). ToArray()); –

6

ich verwendet habe, um dieses BouncyCastle Nuget Paket: https://www.nuget.org/packages/BouncyCastle-PCL/ und es funktioniert gut für mich (cross-Plattformen Windows Store App, .Net Framework 4.5, Silverlight 5, Windows Phone 8, Xamarin. Android, Xamarin.iOS)

Verwenden HMACSHA1 Signatur wie folgt generieren:

public string GenerateSignature(string key, string signatureBase) 
{ 
    var keyBytes = Encoding.UTF8.GetBytes(key); 
    HMACSHA1 hashAlgorithm = new HMACSHA1(keyBytes);    
    byte[] dataBuffer = Encoding.UTF8.GetBytes(signatureBase); 
    byte[] hashBytes = hashAlgorithm.ComputeHash(dataBuffer); 
    return Convert.ToBase64String(hashBytes); 
} 
0

bis ich mich abmelde OAuth wollte auch, und ist auf der Suche PCL Crypto - dieser Test zeigt Schaffung eines HMACSHA1 Hash und vergleicht th Das Ergebnis ist der Standard-.NET Framework-Weg.

[Test] 
    public void CreateHash_VersusComputeHash_ReturnsEquivalent() 
    { 
     // USING TRADITIONAL .NET: 
     var key = new byte[32]; 
     var contentBytes = Encoding.UTF8.GetBytes("some kind of content to hash"); 
     new RNGCryptoServiceProvider().GetBytes(key); 

     var alg = new HMACSHA1(key); // Bouncy castle usage does not differ from this 
     var result = alg.ComputeHash(contentBytes); 




     // USING PCL CRYPTO: 
     var algorithm = WinRTCrypto.MacAlgorithmProvider.OpenAlgorithm(MacAlgorithm.HmacSha1); 

     byte[] mac; 
     using (var hasher = algorithm.CreateHash(key)) 
     { 
      hasher.Append(contentBytes); 
      mac = hasher.GetValueAndReset(); 
     } 




     // Assert results: 
     Assert.AreEqual(result.Length, mac.Length); 

     for (var i = 0; i < result.Length; i++) 
     { 
      Assert.AreEqual(result[i], mac[i]); 
     } 
    } 
1

Sie möchten vielleicht die neue ausprobieren.NET Standard- Bibliothek:

https://docs.microsoft.com/en-us/dotnet/articles/standard/library

Es ist tragbar und System.Security.Cryptography ist im Preis inbegriffen.

/// <summary> 
    /// Compute hash for string encoded as UTF8 
    /// </summary> 
    /// <param name="input">String to be hashed.</param> 
    /// <returns>40-character hex string.</returns> 
    public static string GetSha1(string input) 
    { 
     using (var sha1 = System.Security.Cryptography.SHA1.Create()) 
     { 
      byte[] inputBytes = Encoding.UTF8.GetBytes(input); 
      byte[] hash = sha1.ComputeHash(inputBytes); 

      StringBuilder sb = new StringBuilder(); 
      for (int i = 0; i < hash.Length; i++) 
      { 
       sb.Append(hash[i].ToString("X2")); 
      } 
      return sb.ToString(); 
     } 
    } 

Sie könnten auch etwas Hilfe bekommen (für ein PCL-Projekt mit .NET Standard Library erstellen) hier:

https://xamarinhelp.com/dot-net-standard-pcl-xamarin-forms/

0

Dieser arbeitete für mich, wenn ich das gleiche Ergebnis zu erreichen hatte. Sie können dies mit SHA512 und anderen auch tun.

using System.Security.Cryptography; 

public static string HashSHA1(this string value) 
{ 
    using (var sha = SHA1.Create()) 
    { 
     return Convert.ToBase64String(sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes(value))); 
    } 
} 

-Code zitiert aus: https://xamarinhelp.com/cryptography-in-xamarin-forms/

0

Hier ist ein Beispiel unter Verwendung von BouncyCastle

public static string ComputeSha1(string data) 
    { 
     var sha1Digest = new Org.BouncyCastle.Crypto.Digests.Sha1Digest(); 
     var hash = new byte[sha1Digest.GetDigestSize()]; 

     var dataBytes = Encoding.UTF8.GetBytes(data); 
     foreach (var b in dataBytes) 
     { 
      sha1Digest.Update(b); 
     } 
     sha1Digest.DoFinal(hash, 0); 

     return string.Join("", hash.Select(b => b.ToString("x2")).ToArray()); 
    } 
Verwandte Themen