2009-10-22 17 views
46

Busco un equivalente Java a esta llamada php:equivalente Java de PHP HMAC-SHA1

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

He intentado esto, usando java.crypto.Mac, pero los dos no estoy de acuerdo:

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

Las salidas con clave = "secreto" y prueba = "prueba" no parecen coincidir.

+2

Bueno, ¿cómo difieren? ¿Cuál coincide con los patrones de prueba para sha1? Un vistazo superficial al documento PHP muestra las opciones de "raw_output". –

+0

Publique una entrada y salida de prueba (use codificación hexadecimal o base-64 para parámetros binarios). – erickson

Respuesta

37

De hecho, están de acuerdo.
Como ya notó Hans Doggen, PHP emite el mensaje resumen usando notación hexadecimal a menos que establezca el parámetro de salida sin procesar en verdadero.
Si desea utilizar la misma notación en Java se puede usar algo como

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

para formatear la salida en consecuencia.

3

Me parece que PHP utiliza la notación HEX para los bytes que Java produce (1a = 26) - pero no compruebe la expresión completa.

¿Qué ocurre si ejecuta la matriz de bytes a través del método en la página this?

1

no lo he probado, pero intente esto:

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

Ésta es la instantánea de mi método que hace MD5 y SHA1 partido de php java.

+0

Por supuesto, el uso de StringBuilder nuevo (digest.length * 2), un bucle for/next y append (String.format ("% 02X"), digest [i] y 0xFF) requiere menos memoria y posiblemente sea un poco más legible . –

+0

la sentencia if debe ser un ciclo while. no funcionará para el caso de varios ceros a la izquierda. – slushi

4

Esta es mi aplicación:

 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

Esa es la única solución que funciona para mí. ¡Muchas gracias! –

11

Usted puede probar esto en 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

Mi aplicación para HmacMD5 - apenas cambie algoritmo para 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

esta manera Pude obtener la misma cadena exacta que estaba obteniendo con hash_hmac en 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

Esta debería ser la respuesta correcta, muchos han pasado por alto el paso de codificación Hex. – Krishnaraj