2009-10-22 21 views
46

szukam odpowiednik Java do niniejszego zaproszenia PHP:java równoważne PHP HMAC-SHA1

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

Próbowałem to, używając java.crypto.Mac, ale dwa nie zgadzają się:

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

Wyjścia z kluczem = "secret" i test = "test" nie wydają się pasować.

+2

Cóż, jak one się różnią? Który pasuje do wzorów testowych dla sha1? Rzut oka na dokument PHP pokazuje opcje "raw_output". –

+0

Opublikuj dane wejściowe i wyjściowe testu (użyj kodowania szesnastkowego lub base-64 dla parametrów binarnych). – erickson

Odpowiedz

37

W rzeczywistości się zgadzają.
Jak już zauważył Hans Doggen, PHP wypisuje skrót wiadomości za pomocą notacji szesnastkowej, chyba że ustawiono surowy parametr wyjściowy na true.
Jeśli chcesz użyć tej samej notacji w Javie można użyć coś podobnego

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

do formatowania danych wyjściowych odpowiednio.

3

Wydaje mi się, że PHP używa notacji HEX dla bajtów tworzonych przez Javę (1a = 26) - ale nie sprawdziłem całego wyrażenia.

Co się stanie, jeśli tablica bajtów zostanie uruchomiona za pomocą metody na stronie this?

1

nie testowałem, ale spróbuj tego:

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

To migawka z mojego metody sprawia, że ​​Java jest MD5 i SHA1 mecz php.

+0

Oczywiście użycie nowej StringBuilder (digest.length * 2), pętli for/next i append (String.format ("% 02X"), digest [i] i 0xFF) zajmuje mniej pamięci i może być nieco bardziej czytelne . –

+0

Instrukcja if musi być pętlą while. nie będzie działać w przypadku wielu początkowych zer. – slushi

4

To jest moje wykonanie:

 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

To jedyne rozwiązanie, które działa dla mnie. Wielkie dzięki! –

11

Można spróbować to w Javie:

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

Moja implementacja dla HmacMD5 - wystarczy zmienić algorytm 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

ten sposób Mógłbym uzyskać dokładnie ten sam napis jaki otrzymałem z hash_hmac w 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

To powinna być właściwa odpowiedź, wielu opuściło krok kodowania Hex. – Krishnaraj