Implementación de Criptografía en Java con JCA y JCE

Las arquitecturas de seguridad en el ecosistema Java se basan fundamentalmente en la Java Cryptography Architecture (JCA) y la Java Cryptography Extension (JCE). Estos frameworks proporcionan las enterfaces y proveedores necesarios para implementar cifrado simétrico, asimétrico y algoritmos de resumen criptográfico.

Cifrado Simétrico con AES

El cifrado simétrico utiliza una única clave secreta tanto para ofuscar como para recuperar los datos. Para garantizar un nivel de seguridad adecuado en producción, es imperativo utilizar un modo de operación que incluya un Vector de Inicialización (IV), como el modo CBC.

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.security.SecureRandom;
import java.util.Base64;

public class CifradoSimetrico {
    public static void main(String[] args) {
        try {
            String datosOriginales = "Informacion sensible a proteger";

            // Generación de clave y vector de inicialización (IV)
            KeyGenerator generadorClave = KeyGenerator.getInstance("AES");
            generadorClave.init(256);
            SecretKey claveSecreta = generadorClave.generateKey();

            byte[] iv = new byte[16];
            new SecureRandom().nextBytes(iv);
            IvParameterSpec ivSpec = new IvParameterSpec(iv);

            // Proceso de cifrado con modo CBC y relleno PKCS5
            Cipher cifrador = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cifrador.init(Cipher.ENCRYPT_MODE, claveSecreta, ivSpec);
            byte[] datosCifrados = cifrador.doFinal(datosOriginales.getBytes("UTF-8"));

            String resultadoCifrado = Base64.getEncoder().encodeToString(datosCifrados);
            System.out.println("Payload cifrado: " + resultadoCifrado);

            // Proceso de descifrado utilizando el mismo IV
            cifrador.init(Cipher.DECRYPT_MODE, claveSecreta, ivSpec);
            byte[] datosRecuperados = cifrador.doFinal(Base64.getDecoder().decode(resultadoCifrado));

            System.out.println("Payload descifrado: " + new String(datosRecuperados, "UTF-8"));
        } catch (Exception e) {
            System.err.println("Fallo en la operación simétrica: " + e.getMessage());
        }
    }
}

Cifrado Asimétrico con RSA

La criptografía de clave pública emplea un par de claves matemáticamente vinculadas: una pública para el cifrado y una privada para el descifrado. Este enfoque es fundamental para el intercambio seguro de claves y las firmas digitales.

import javax.crypto.Cipher;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Base64;

public class CifradoAsimetrico {
    public static void main(String[] args) {
        try {
            String mensajePlano = "Credenciales de acceso";

            // Creación del par de claves asimétricas de 4096 bits
            KeyPairGenerator generadorRSA = KeyPairGenerator.getInstance("RSA");
            generadorRSA.initialize(4096); 
            KeyPair parClaves = generadorRSA.generateKeyPair();
            PublicKey clavePublica = parClaves.getPublic();
            PrivateKey clavePrivada = parClaves.getPrivate();

            // Cifrado utilizando la clave pública
            Cipher motorCifrado = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            motorCifrado.init(Cipher.ENCRYPT_MODE, clavePublica);
            byte[] bloqueCifrado = motorCifrado.doFinal(mensajePlano.getBytes("UTF-8"));
            
            String dataEncriptada = Base64.getEncoder().encodeToString(bloqueCifrado);
            System.out.println("Data encriptada: " + dataEncriptada);

            // Descifrado utilizando la clave privada
            motorCifrado.init(Cipher.DECRYPT_MODE, clavePrivada);
            byte[] bloqueDescifrado = motorCifrado.doFinal(bloqueCifrado);
            
            System.out.println("Data original recuperada: " + new String(bloqueDescifrado, "UTF-8"));
        } catch (Exception ex) {
            System.err.println("Error en operación RSA: " + ex.getMessage());
        }
    }
}

Generación de Hashes con SHA-256

Las funciones hash criptográficas transforman datos de longitud arbitraria en una cadena de longitud fija. Son operaciones unidireccionales diseñadas para verificar la integridad de la información.

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;

public class GeneradorHash {
    public static void main(String[] args) {
        try {
            String textoEntrada = "Validacion de integridad de datos";
            MessageDigest algoritmoHash = MessageDigest.getInstance("SHA-256");
            
            byte[] resumenDigital = algoritmoHash.digest(textoEntrada.getBytes(StandardCharsets.UTF_8));
            
            // Conversión del arreglo de bytes a representación hexadecimal
            StringBuilder constructorHex = new StringBuilder();
            for (byte b : resumenDigital) {
                constructorHex.append(String.format("%02x", b));
            }
            
            System.out.println("Resumen SHA-256: " + constructorHex.toString());
        } catch (Exception error) {
            error.printStackTrace();
        }
    }
}

Prácticas Recomendadas de Implementcaión

  • Gestión de Claves: Evite codificar claves directamente en el código fuente. Utilice almacenes de claves seguros como KeyStore o soluciones de gestión de secretos externas (KMS).
  • Modos de Operación: Nunca utilice el modo ECB (Electronic Codebook) para AES, ya que expone patrones en los datos. Prefiera modos autenticados como GCM o al manos CBC con un IV aleatorio.
  • Relleno (Padding): Asegúrese de definir explícitamente el esquema de relleno (ej. PKCS5Padding, PKCS1Padding) para evitar vulnerabilidades como los ataques de relleno oracle.
  • Manejo de Excepciones: Las operaciones criptográficas lanzan múltiples excepciones comprobadas (NoSuchAlgorithmException, InvalidKeyException, etc.). Deben ser capturadas y gestionadas sin exponer información sensible en los logs.

Comparativa de Algoritmos Comunes

Categoría Algoritmo Características Principales
Cifrado Simétrico AES Estándar moderno, alto rendimiento y seguridad robusta.
Cifrado Simétrico DES / 3DES Estándares heredados, actualmente considerados obsoletos e inseguros.
Cifrado Asimétrico RSA Basado en factorización de enteros, ideal para intercambio de claves.
Cifrado Asimétrico ECC Criptografía de curva elíptica, ofrece seguridad equivalente con claves más cortas.
Función Hash SHA-256 Algoritmo de la familia SHA-2, produce un resumen de 256 bits resistente a colisiones.
Función Hash MD5 Generador de hashes de 128 bits, altamente vulnerable y en desuso.

Etiquetas: java JCA jce AES RSA

Publicado el 8-12 00:11