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]