Generación y Verificación de Códigos de Autenticación de Mensajes (MAC) en Java

Los resúmenes de mensajes, como MD5, calculan un valor de hash a partir de un texto o archivo. Este hash se envía junto con los datos originales. El receptor recalcula el hash de los datos recibidos y compara ambos hashes. Si coinciden, se asume que los datos no han sido alterados.

Sin embargo, este método es vulnerable. Si un tercero intercepta el mensaje, puede modificar los datos y recalcular el hash para que coincida con los datos alterados. El receptor no detectaría la manipulación, y tampoco se verifica la identidad del remitente.

Para abordar estas limitaciones, se utilizan los Códigos de Autenticación de Mensajes (MAC), que emplean funciones hash con una clave secreta compartida.

Códigos de Autenticación de Mensajes (MAC)

Un MAC es un mecanismo de autenticación que garantiza la integridad de los datos y, en combinación con el secreto compartido, puede verificar la autenticidad del remitente. El proceso implica que ambas partes de la comunicación compartan una clave secreta. El remitente utiliza una función hash acordada y la clave secreta para generar un código MAC a partir de los datos. Este MAC se envía junto con los datos originales.

Al recibir el mensaje, el receptor utiliza la misma clave secreta y función hash para recalcular el MAC de los datos recibidos. Luego, compara este MAC calculado con el MAC recibido. Si coinciden, se considera que el mensaje es auténtico e íntegro.

Es crucial entender que la generación del MAC requiere una clave secreta. Sin esta clave, es imposible calcular el MAC. Además, incluso para el mismo mensaje, diferentes claves secretas producirán MACs distintos.

Demostración en Java (JDK 1.8)

A continuación, se muestra un ejemplo en Java para calcular el MAC de un archivo usando HmacMD5 y HmacSHA256 con una clave compartida.


package com.security.mac;

import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.Key;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Hex;

public class MessageAuthCodeGenerator {

    // Clave secreta compartida entre las partes comunicantes
    private static final String SHARED_SECRET_KEY = "a1b2c3d4e5f678901234567890abcdef";

    /**
     * Calcula el MAC para los datos proporcionados usando un algoritmo y clave específicos.
     *
     * @param algorithm El nombre del algoritmo MAC a utilizar (ej. "HmacMD5", "HmacSHA256").
     * @param key La clave secreta para la generación del MAC.
     * @param data Los datos de entrada para los cuales se calculará el MAC.
     * @return El valor del MAC calculado como un arreglo de bytes.
     * @throws Exception Si ocurre un error durante el proceso de generación del MAC.
     */
    public static byte[] generateMac(String algorithm, Key key, byte[] data) throws Exception {
        Mac macEngine = Mac.getInstance(algorithm);
        // Inicializa el motor MAC con la clave secreta compartida
        macEngine.init(key);
        
        // Calcula y devuelve el MAC
        return macEngine.doFinal(data);
    }
    
    public static void main(String[] args) throws Exception {
        // Carga el contenido del archivo en un arreglo de bytes
        byte[] fileContent = Files.readAllBytes(Paths.get("path/to/your/sample.zip"));
        
        // Crea un objeto Key a partir de la clave secreta compartida
        Key secretKey = new SecretKeySpec(SHARED_SECRET_KEY.getBytes(), "");
        
        // Calcula el MAC usando HmacMD5
        byte[] hmacMd5Mac = generateMac("HmacMD5", secretKey, fileContent);
        
        // Calcula el MAC usando HmacSHA256
        byte[] hmacSha256Mac = generateMac("HmacSHA256", secretKey, fileContent);
        
        // Convierte los resultados del MAC a cadenas hexadecimales para su visualización
        System.out.println("HmacMD5 MAC: " + Hex.encodeHexString(hmacMd5Mac));
        System.out.println("HmacSHA256 MAC: " + Hex.encodeHexString(hmacSha256Mac));
    }
}

Los algoritmos MAC disponibles en Java se pueden obtener programáticamente. Por ejemplo, en Java 8, se puede listar los algoritmos de MAC compatibles de la siguiente manera:


import java.security.Security;

// ...

Security.getAlgorithms("Mac").forEach(System.out::println);

La salida de este código en Java 8 puede incluir algoritmos como: HmacMD5, HmacSHA1, HmacSHA256, HMACSHA384, entre otros.

Ejemplo de salida de MACs calculados:


5e08b186b9b4f3a10d67c21e87e488d0
f21c9ed3b01e81d235f18d4e5a9aeb00183e253e44b6ed763328ff97f856200

Estos MACs calculados pueden ser verificados externamente, por ejemplo, utilizando herramientas como OpenSSL, siempre que se proporcione la misma clave secreta utilizada en Java.

Etiquetas: java Mac HmacMD5 HmacSHA256 criptografía

Publicado el 7-31 02:21