2009-10-22 11 views
46

Sto cercando un java equivalente a questa chiamata php:java equivalente di php HMAC-SHA1

hash_hmac('sha1', "test", "secret") 

ho provato questo, utilizzando java.crypto.Mac, ma i due non sono d'accordo:

String mykey = "secret"; 
String test = "test"; 
try { 
    Mac mac = Mac.getInstance("HmacSHA1"); 
    SecretKeySpec secret = new SecretKeySpec(mykey.getBytes(),"HmacSHA1"); 
    mac.init(secret); 
    byte[] digest = mac.doFinal(test.getBytes()); 
    String enc = new String(digest); 
    System.out.println(enc); 
} catch (Exception e) { 
    System.out.println(e.getMessage()); 
} 

Le uscite con key = "secret" e test = "test" non sembrano corrispondere.

+2

Bene, come si differenziano? Quale corrisponde ai modelli di prova per sha1? Una rapida occhiata al documento PHP mostra le opzioni "raw_output". –

+0

Pubblica alcuni input e output di test (usa codifica esadecimale o base-64 per i parametri binari). – erickson

risposta

37

In effetti sono d'accordo.
Come già notato da Hans Doggen, PHP esegue il digest del messaggio utilizzando la notazione esadecimale, a meno che non si imposti il ​​parametro di output non elaborato su true.
Se si desidera utilizzare la stessa notazione in Java si può usare qualcosa di simile

for (byte b : digest) { 
    System.out.format("%02x", b); 
} 
System.out.println(); 

per formattare l'output di conseguenza.

3

Mi sembra che PHP usi la notazione HEX per i byte prodotti da Java (1a = 26), ma non ho controllato l'intera espressione.

Cosa succede se si esegue l'array di byte tramite il metodo sulla pagina this?

1

non ho ancora testato, ma provate questo:

 BigInteger hash = new BigInteger(1, digest); 
     String enc = hash.toString(16); 
     if ((enc.length() % 2) != 0) { 
      enc = "0" + enc; 
     } 

Questa è un'istantanea dal mio metodo che rende MD5 e SHA1 partita php di Java.

+0

Ovviamente, usando il nuovo StringBuilder (digest.length * 2), un ciclo for/next e append (String.format ("% 02X"), digest [i] & 0xFF) richiede meno memoria e forse un po 'più leggibile . –

+0

l'istruzione if deve essere un ciclo while. non funzionerà per il caso degli zeri iniziali multipli. – slushi

4

Questa è la mia realizzazione:

 String hmac = ""; 

    Mac mac = Mac.getInstance("HmacSHA1"); 
    SecretKeySpec secret = new SecretKeySpec(llave.getBytes(), "HmacSHA1"); 
    mac.init(secret); 
    byte[] digest = mac.doFinal(cadena.getBytes()); 
    BigInteger hash = new BigInteger(1, digest); 
    hmac = hash.toString(16); 

    if (hmac.length() % 2 != 0) { 
     hmac = "0" + hmac; 
    } 

    return hmac; 
+0

Questa è l'unica soluzione che funziona per me. Molte grazie! –

11

si può provare questo in Java:

private static String computeSignature(String baseString, String keyString) throws GeneralSecurityException, UnsupportedEncodingException { 

    SecretKey secretKey = null; 

    byte[] keyBytes = keyString.getBytes(); 
    secretKey = new SecretKeySpec(keyBytes, "HmacSHA1"); 

    Mac mac = Mac.getInstance("HmacSHA1"); 

    mac.init(secretKey); 

    byte[] text = baseString.getBytes(); 

    return new String(Base64.encodeBase64(mac.doFinal(text))).trim(); 
} 
1

mio implementazione per HMACMD5 - basta cambiare algoritmo per HmacSHA1:

SecretKeySpec keySpec = new SecretKeySpec("secretkey".getBytes(), "HmacMD5"); 
Mac mac = Mac.getInstance("HmacMD5"); 
mac.init(keySpec); 
byte[] hashBytes = mac.doFinal("text2crypt".getBytes()); 
return Hex.encodeHexString(hashBytes); 
1

In questo modo Potrei ottenere esattamente la stessa stringa di hash_hmac in php

String result; 

try { 
     String data = "mydata"; 
     String key = "myKey"; 
     // Get an hmac_sha1 key from the raw key bytes 
     byte[] keyBytes = key.getBytes(); 
     SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA1"); 

     // Get an hmac_sha1 Mac instance and initialize with the signing key 
     Mac mac = Mac.getInstance("HmacSHA1"); 
     mac.init(signingKey); 

     // Compute the hmac on input data bytes 
     byte[] rawHmac = mac.doFinal(data.getBytes()); 

     // Convert raw bytes to Hex 
     byte[] hexBytes = new Hex().encode(rawHmac); 

     // Covert array of Hex bytes to a String 
     result = new String(hexBytes, "ISO-8859-1"); 
     out.println("MAC : " + result); 
} 
catch (Exception e) { 

} 
+0

Questa dovrebbe essere la risposta giusta, molti hanno perso la fase di codifica esadecimale. – Krishnaraj