2013-01-08 14 views
5

Ho un esempio di codice java per eseguire un digest utilizzando l'algoritmo HMAC-SHA1 (RFC 2104.), quindi codificato utilizzando la codifica Base64 (RFC 2045).C# vs Java HmacSHA1 e quindi base64

Ecco il codice Java

public static String buildDigest(String key, String idString) throws SignatureException { 


try { 
    String algorithm = "HmacSHA1"; 
    Charset charset = Charset.forName("utf-8"); 
    SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), algorithm); 
    Mac mac = Mac.getInstance(algorithm); 
    mac.init(signingKey); 
    return new String(Base64.encodeBase64(mac.doFinal(idString.getBytes(charset))), charset); 
    } catch (Exception e) { 
    throw new SignatureException("Failed to generate HMAC : " + e.getMessage()); 
    } 
} 

ho trovato risposte qui in Stack Overflow: ecco il codice C#

private string EncodeHMAC(string input, byte[] key) 
    { 
     HMACSHA1 myhmacsha1 = new HMACSHA1(key); 
     byte[] byteArray = Encoding.UTF8.GetBytes(input); 
     // MemoryStream stream = new MemoryStream(byteArray); 
     var hashValue = myhmacsha1.ComputeHash(byteArray); 
     return hashValue.Aggregate("", (s, e) => s + String.Format("{0:x2}", e), s => s); 
    } 

    private string EncodeTo64(string toEncode) 
    { 
     byte[] toEncodeAsBytes = System.Text.UTF8Encoding.UTF8.GetBytes(toEncode); 

     string returnValue = System.Convert.ToBase64String(toEncodeAsBytes); 

     return returnValue; 
    } 

Non ricevo i giusti risultati mostrati nella tutorial that I am following

+0

Perché passate la chiave come stringa nella versione Java? Sei sicuro che il risultato del metodo Java 'key.getBytes()' è equivalente all'array di byte che stai utilizzando nella versione C#? Se capisco correttamente il tuo codice C#, restituisce anche l'HMAC hex codificato, mentre la versione Java usa Base64. – jarnbjo

risposta

7

Prova questo:

// This method will return the base 64 encoded string using the given input and key. 
private string EncodeHMAC(string input, byte[] key) 
{ 
    HMACSHA1 hmac = new HMACSHA1(key); 
    byte[] stringBytes = Encoding.UTF8.GetBytes(input); 
    byte[] hashedValue = hmac.ComputeHash(stringBytes); 
    return Convert.ToBase64String(hashedValue); 
} 

Non penso che si stia convertendo correttamente il valore hash in una stringa 64 di base.

2

Uso questa funzione per implementare l'autenticazione delle chiamate al servizio web REST. È importante che mittente e destinatario utilizzino la stessa codifica.

Sfortunatamente mi ci è voluto un po 'per trovare una implementazione HAMAC PHP corrispondente a questa versione di C#.

private bool ValidateHash(String uid, String hash, DataToSign data) { 
     StringBuilder strToSign = new StringBuilder(); 

     strToSign.Append(data.HttpMethod + '\n'); 
     strToSign.Append(data.Date.ToString("r") + '\n'); 
     strToSign.Append(data.Uri); 

     Byte[] secretBytes = UTF8Encoding.UTF8.GetBytes(this._secretKey); 
     HMACSHA1 hmac = new HMACSHA1(secretBytes); 

     Byte[] dataBytes = UTF8Encoding.UTF8.GetBytes(strToSign.ToString()); 
     Byte[] calcHash = hmac.ComputeHash(dataBytes); 
     String calcHashString = Convert.ToBase64String(calcHash); 

     if (calcHashString.Equals(hash)) { 
      if (log.IsDebugEnabled) log.Debug(uid + " - [ValidateHash] HMAC is valid."); 
      return true; 
     } 
     return false; 
    } 

Spero che ti aiuti!

+0

Se si intende utilizzare un generatore di stringhe, non concatenare stringhe all'interno del metodo append! Se vuoi aggiungere una nuova riga alla fine della tua stringa, fallo invece: 'strToSign.AppendLine (data.HttpMethod)' – RobH

+0

@RobH hai ragione - è da un po 'che ho scritto questo. – Andreas