2012-04-20 17 views
15

Estoy intentando crear una biblioteca de clases portátil que genere urls OAuth para otras clases/aplicaciones. Esta biblioteca de clases que usa OAuth tiene que ser una biblioteca de clases portátil, por lo que puede funcionar con diferentes versiones de una API de DropBox que estoy creando.Generar Hash SHA1 en la Biblioteca de clases portátil

Parte de esta clase necesita generar un hash SHA1 para generar la firma oauth_signature.

Soy consciente de que la biblioteca de clases portátil no es compatible con System.Security.Cryptography, por lo que de todos modos, ¿esta clase puede generar un hash SHA1 sin esa clase?

+2

podría copiar más de un código de Mono.Security. – CodesInChaos

+2

No veo ninguna dependencia problemática en la clase SHA1Managed. Portable me parece simplemente inacabado cada vez que eche un vistazo. –

+0

Eso sería un problema, pero es una clase de construcción de cuerdas bastante simple con un par de métodos, por lo que siempre y cuando su trabajo sea inacabado no es un problema. –

Respuesta

6

Mono proporciona un managed implementation of SHA1 por su propio mscorlib.dll (pero no se encuentra en Mono.Security.dll como @CodeInChaos sugirió).

Es de código abierto, muy bien probado y significaba que se comporten exactamente igual implementación de Microsoft (por ejemplo, que se deriva de SHA1, HashAlgorith ... implementa ICryptoTransform ...) por lo que debe ser una gota en el reemplazo fácil.

+0

¿Podría ayudarme un poco usándolo simplemente con una cadena? El código prácticamente no tiene comentarios sobre él, así que me resulta difícil de entender. –

+1

Necesita transformar la cadena en bytes, p. 'System.Text.XXXEncoding.GetBytes()'. Tenga mucho cuidado con las codificaciones de wrt (por ejemplo, UTF8 es mucho mejor que ASCII) ya que diferentes bytes darán como resultado diferentes valores de hash. – poupou

+0

No sé cómo usar esto. ¿Alguien puede ayudarme a generar un hash SHA1 de alguna cadena? – alvaropaco

2

El SHA-1 Wikipedia article contiene un pseudocódigo que puede usar como guía para su propia implementación. Pero, como siempre con las funciones criptográficas, recomiendo utilizar una implementación probada.

Suponiendo que desea una implementación de SHA-256, puede encontrar una en BouncyCastle, que está disponible en forma de código fuente. La clase relevante allí se llama Org.BouncyCastle.Crypto.Digests.Sha256Digest (aquí está su source).

8

Bueno, yo necesitaba esto también hace poco y me pareció mucho más fácil tomar la implementación de SHA1 HashLib: http://hashlib.codeplex.com/

aplicación mono tienen algunas dependencias de largo en curso (localización de excepciones, etc.), mientras que desde HashLib sólo es necesario para copiar algunos archivos sin ningún cambio en ellos:

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

55 KB de código total, por lo que nada demasiado pesado.

+0

funcionó para mí. Sin embargo, tuve que agregar algunos archivos adicionales a tu lista. IHashInfo.cs (no se necesitó todo). ArrayExtentions.cs también fue necesario para el método de extensión .SubArray() utilizado en una de las clases mencionadas anteriormente. La clase HashFactory se redujo para que coincida con las clases portadas, pero hace el trabajo bien. Gracias por los consejos. Originalmente, mi cabeza daba vueltas mirando todas las clases. Tu lista realmente ayudó. – TravisWhidden

+0

Esto funciona bastante bien, ¡gracias! Al igual que mencionó rouen, IHashInfo.cs no se encuentra en su lista. Como solo necesitaba una cadena para la conversión de SHA1, pude reducir el tamaño del código a ~ 26 KB. –

16

Creo que la manera más fácil es usar el paquete PCLCrypto nuget. A continuación, puede hacer:

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

Acepto, pero es posible que desee modificar el ejemplo para mostrar una clave en uso: byte [] claveMaterial; byte [] datos; var algorithm = WinRTCrypto.MacAlgorithmProvider.OpenAlgorithm (MacAlgorithm.HmacSha1); CryptographicHash hasher = algorithm.CreateHash (keyMaterial); hasher.Append (datos); byte [] mac = hasher.GetValueAndReset(); cadena macBase64 = Convert.ToBase64String (mac); –

+0

¡Gran ejemplo! Tengo una pequeña adición. Creando cadena hexagonal en una fila en lugar de 5: devuelve cadena.Únete ("", hash.Seleccione (b => b.ToString ("x2")). ToArray()); –

6

He utilizado este paquete BouncyCastle Nuget: https://www.nuget.org/packages/BouncyCastle-PCL/ y funciona muy bien para mí (plataformas cruzadas de Windows App Store, .Net Framework 4.5, Silverlight 5, Windows Phone 8, Xamarin. androide, Xamarin.iOS)

uso HMACSHA1 para generar la firma de esta manera:

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

que querían firmar OAuth también, y estoy buscando en PCL Crypto - esta prueba muestra la creación de un hash HMACSHA1, y compara th El resultado es el camino estándar de .NET Framework.

[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

Es posible que desee comprobar el nuevo .NET estándar biblioteca:

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

Es portátil y System.Security.Cryptography está incluido.

/// <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(); 
     } 
    } 

También puede obtener un poco de ayuda (para la creación de un proyecto PCL con .NET Standard Library) aquí:

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

0

Esto funcionó para mí cuando tuve que conseguir el mismo resultado. Puede hacer esto con SHA512 y otros también.

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

Código citado de: https://xamarinhelp.com/cryptography-in-xamarin-forms/

0

Aquí hay un ejemplo usando 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()); 
    } 
Cuestiones relacionadas