Cada vez más APIs utilizan resúmenes (hashes) HMAC-SHA1 porque permiten unificar autenticación del cliente y verficación de integridad del mensaje en un sólo paso. Java sigue siendo el lenguaje de programación más utilizado a nivel empresarial, así que a continuación se explica cómo generar dos resúmenes HMAC-SHA1
: primero de forma nativa sin ayudas de librerías externas (paquete javax.crypto
) y después con ayuda de la Apache Commons Codec.
Java sin librerías externas (a partir de Java 1.4)
package org.ingenieroinformatico.examples.hmacsha1; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.util.Arrays; public class Main { public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException { final String contentToHash = "{\"cpu\": {\"manufacturer\": \"AMD\", \"model\": \"Ryzen 7 1800X\"}}"; final String key = "DontUseThisPassword"; /* Se inicializa el generador del algoritmo MAC. El algoritmo es HmacSHA1, pero podría ser otro: HmacSHA256 o HmacMD5. Si es no es válido el algoritmo se lanza una NoSuchAlgorithmException */ Mac hmacSha1 = Mac.getInstance("HmacSHA1"); /* Se construye la clave secreta a partir de su valor serializado como String, pero podrían ser los bytes en un fichero. Hay que indicar el algoritmo también. Si la clave contiene bytes no permitidos o longitud inadecuada se lanza InvalidKeyException */ SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "HmacSHA1"); // Se le indica al algoritmo la clave privada a usar: hmacSha1.init(secretKey); // Finalmente se generan los bytes del resumen: byte[] hmacSha1Hash = hmacSha1.doFinal(contentToHash.getBytes()); /* Mostramos los bytes encriptados. Lo habitual es codificarlos en base64 y adjuntarlos en una cabecera del servicio web. */ System.out.println("HMAC-SHA1: " + Arrays.toString(hmacSha1Hash)); } }
Si se ejecuta el código anterior se obtiene la salida:
HMAC-SHA1: [-121, 84, -63, -47, -49, 17, -64, -28, -123, -75, 93, 53, 104, 35, -121, 84, -26, 73, 12, -119]
Java con librería Apache Commons Codec 1.10 (o superior)
Obviamente, con la librería de Apache el código se simplifica bastante a cambio de una mayor sobrecarga:
package org.ingenieroinformatico.examples.hmacsha1; import java.util.Arrays; import org.apache.commons.codec.digest.HmacUtils; public class Main { public static void main(String[] args) throws IllegalArgumentException { final String contentToHash = "{\"cpu\": {\"manufacturer\": \"AMD\", \"model\": \"Ryzen 7 1800X\"}}"; final String key = "DontUseThisPassword"; /* Se generan los bytes del resumen con la clave y el contenido directamente. Si la clave no es válida arroja IllegalArgumentException. */ byte[] hmacSha1Hash = HmacUtils.hmacSha1(key, contentToHash); /* Mostramos los bytes encriptados. Lo habitual es codificarlos en base64 y adjuntarlos en una cabecera del servicio web. */ System.out.println("HMAC-SHA1: " + Arrays.toString(hmacSha1Hash)); } }
El código anterior arroja la salida deseada:
HMAC-SHA1: [-121, 84, -63, -47, -49, 17, -64, -28, -123, -75, 93, 53, 104, 35, -121, 84, -26, 73, 12, -119]