Criptografía

Uso de criptografía en Java

Criptografía

Encriptación:

 

 

 

Criptografía en Java

Arquitectura Criptográfica de Java (JCA)

Obtener la lista completa de los proveedores disponibles en tu sistema:

ObtenerListaProveedores.java

import java.security.Provider;
import java.security.Security;

public class ObtenerListaProveedores {
    public static void main(String[] args) {

        // Obtener todos los proveedores de seguridad
        Provider[] providers = Security.getProviders();

        for (Provider provider : providers) {
            System.out.printf("Proveedor: %s\n", provider.getName());
        }
    }
}

Ejecición

javac ObtenerListaProveedores.java
java ObtenerListaProveedores

Obtener la lista de servicios de esos proveedores:

ObtenerListaServicios.java

import java.security.Provider;
import java.security.Security;
import java.util.Set;

public class ObtenerListaServicios {
    public static void main(String[] args) {

        // Obtener todos los proveedores de seguridad
        Provider[] providers = Security.getProviders();

        for (Provider provider : providers) {
            // Obtener los servicios de MessageDigest del proveedor
            Set<Provider.Service> services = provider.getServices();

            System.out.printf("Proveedor: %s\n", provider.getName());
            System.out.printf("-----------%s\n", "-".repeat(provider.getName().length()));
            for (Provider.Service service : services) {
                // Obtener el servicio (algoritmo)
                String algoritmo = service.getAlgorithm();

                // Imprimir el algoritmo 
                System.out.printf("Servicio: %s - Tipo: %s\n",
                        algoritmo, service.getType());
            }
            System.out.println();
        }

    }
}

Obtener más información:

InfoProveedores.java

// InfoProveedores.java
import java.security.*;
import java.util.*;

class InfoProveedores {
  public static void main(String[] args) {
    boolean listarProps = false;
    if ( args.length > 0 && args[0].equals("-l") )
      listarProps=true;
    System.out.println("------------------------------------");
    System.out.println("Proveedores instalados en su sistema");
    System.out.println("------------------------------------");
    Provider[] listaProv = Security.getProviders();
    for (int i = 0; i < listaProv.length; i++) {
      System.out.println("Núm. proveedor : "    + (i + 1));
      System.out.println("Nombre         : "    + listaProv[i].getName());
      System.out.println("Versión        : "    + listaProv[i].getVersion());
      System.out.println("Información    :\n  " + listaProv[i].getInfo());
      System.out.println("Propiedades    :");
      if (listarProps) {
        Enumeration propiedades = listaProv[i].propertyNames();
        while (propiedades.hasMoreElements()) {
          String clave = (String) propiedades.nextElement();
          String valor = listaProv[i].getProperty(clave);
          System.out.println("  " + clave + " = " + valor);
        }
      }
      System.out.println("------------------------------------");
    }
  }
}

Generación de claves

Claves.java

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;

public class Claves {
    //Programa que crea una pareja de claves (pública y privada) y las muestra
    public static void main(String[] args) {

        //Asigna al objeto claves de tipo keyPair el par de claves generadas
        //por el método GeneraParejaClave()
        System.out.println ("Generando pareja de claves pública-privada (PKI)\n");
        KeyPair claves = null;
        try {
            //Crea el objeto para generar un par de claves mediante RSA
            KeyPairGenerator genera = KeyPairGenerator.getInstance("RSA");
            genera.initialize(512); //asigna tamaño de la clave
            claves = genera.generateKeyPair(); //genera la pareja de claves
        } catch (NoSuchAlgorithmException ex) {
            System.out.printf ("Error: %s\n", ex.getMessage());
            ex.printStackTrace();
        }

        //Imprime el valor de las claves generadas
        if (claves != null) {
            System.out.println ("Pareja de claves generada");
            System.out.println ("-------------------------");
            System.out.printf("Algoritmo Kprivada: %s\n\n", claves.getPrivate().getAlgorithm());
            System.out.printf("Codificación Kprivada: %s\n\n", claves.getPrivate().getFormat());
            System.out.printf("Bytes Kprivada: %s\n\n", claves.getPrivate().toString());
            System.out.printf("Algoritmo Kpública: %s\n\n", claves.getPublic().getAlgorithm());
            System.out.printf("Codificación Kpública: %s\n\n", claves.getPublic().getFormat());
            System.out.printf("Bytes Kpública: %s\n\n", claves.getPublic().toString());
        }
    }
}

Resúmenes de mensajes (Hash)

Hash.java

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Hash {
    public static void main(String[] args) {
        String[] listaAlgoritmos = {"MD5", "SHA-1", "SHA-256", "SHA-384", "SHA-512"};
        String texto = "Texto de ejemplo para generar resumen";

        System.out.printf("Texto: %s\n", texto);
        for (int i = 0; i < listaAlgoritmos.length; i++) {

            try {
                MessageDigest algoritmoHash = MessageDigest.getInstance(listaAlgoritmos[i]);

                algoritmoHash.update(texto.getBytes()); //obtiene el resumen
                byte[] resumen = algoritmoHash.digest(); //completa la generación del resumen

                // Convertimos el array de bytes a una representación hexadecimal "legible" por humanos
                StringBuilder sb = new StringBuilder();
                for (byte b : resumen) {
                    sb.append(String.format("%02x", b));
                }
                // Mostramos el resumen por pantalla
                System.out.printf("Resumen %s: %s\n", listaAlgoritmos[i], sb.toString());
            } catch (NoSuchAlgorithmException ex) {
                System.out.printf("Error: %s\n", ex.getMessage());
            }
        }
    }
}

Ejemplos de encriptación simétrica y asímetrica con Cipher

Algoritmos de cifrado simétrico

CifradoDES.java

import java.security.*; //JCA
import javax.crypto.*; //JCE
import java.io.*; //ficheros

//Programa que encripta y desencripta un fichero
//mediante clave privada o simétrica utilizando el algoritmo DES
public class CifradoDES {

    public static void main(String[] Args) {
        //declara e incializa objeto tipo clave secreta
        SecretKey clave = null;

        //llama a los métodos que encripta/desencripta un fichero
        try {
            //Llama al método que encripta el fichero que se pasa como parámetro
            clave = cifrarFichero("./fichero.txt");
            //Llama la método que desencripta el fichero pasado como primer parámetro
            descifrarFichero("./fichero.txt.cifrado", clave,
                    "./fichero.descifrado.txt");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //método que encripta el fichero que se pasa como parámetro
    //devuelve el valor de la clave privada utilizada en encriptación
    //El fichero encriptado lo deja en el archivo de nombre fichero.cifrado
    //en el mismo directorio
    private static SecretKey cifrarFichero(String file) throws NoSuchAlgorithmException, NoSuchPaddingException, FileNotFoundException, IOException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException {
        FileInputStream fe = null; //fichero de entrada
        FileOutputStream fs = null; //fichero de salida
        int bytesLeidos;

        //1. Crear e inicializar clave
        System.out.println("1.-Genera clave DES");
        //crea un objeto para generar la clave usando algoritmo DES
        KeyGenerator keyGen = KeyGenerator.getInstance("DES");
        keyGen.init(56); //se indica el tamaño de la clave
        SecretKey clave = keyGen.generateKey(); //genera la clave privada

        System.out.println("Clave");
        mostrarBytes(clave.getEncoded()); //muestra la clave
        System.out.println();

        //Se Crea el objeto Cipher para cifrar, utilizando el algoritmo DES
        Cipher cifrador = Cipher.getInstance("DES");
        //Se inicializa el cifrador en modo CIFRADO o ENCRIPTACIÓN
        cifrador.init(Cipher.ENCRYPT_MODE, clave);
        System.out.println("2.- Cifrar con DES el fichero: " + file + ", y dejar resultado en " + file + ".cifrado");

        //declaración  de objetos
        byte[] buffer = new byte[1000]; //array de bytes
        byte[] bufferCifrado;
        fe = new FileInputStream(file); //objeto fichero de entrada
        fs = new FileOutputStream(file + ".cifrado"); //fichero de salida
        //lee el fichero de 1k en 1k y pasa los fragmentos leidos al cifrador
        bytesLeidos = fe.read(buffer, 0, 1000);
        while (bytesLeidos != -1) {//mientras no se llegue al final del fichero
            //pasa texto claro al cifrador y lo cifra, asignándolo a bufferCifrado
            bufferCifrado = cifrador.update(buffer, 0, bytesLeidos);
            fs.write(bufferCifrado); //Graba el texto cifrado en fichero
            bytesLeidos = fe.read(buffer, 0, 1000);
        }
        bufferCifrado = cifrador.doFinal(); //Completa el cifrado
        fs.write(bufferCifrado); //Graba el final del texto cifrado, si lo hay
        //Cierra ficheros
        fe.close();
        fs.close();
        return clave;
    }
    //método que desencripta el fichero pasado como primer parámetro file1
    //pasándole también la clave privada que necesita para desencriptar, key
    //y deja el fichero desencriptado en el tercer parámetro file2

    private static void descifrarFichero(String file1, SecretKey key, String file2) throws NoSuchAlgorithmException, NoSuchPaddingException, FileNotFoundException, IOException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException {
        FileInputStream fe = null; //fichero de entrada
        FileOutputStream fs = null; //fichero de salida
        int bytesLeidos;
        Cipher cifrador = Cipher.getInstance("DES");
        //3.- Poner cifrador en modo DESCIFRADO o DESENCRIPTACIÓN
        cifrador.init(Cipher.DECRYPT_MODE, key);
        System.out.println("3.- Descifrar con DES el fichero: " + file1
                + ", y dejar en  " + file2);
        fe = new FileInputStream(file1);
        fs = new FileOutputStream(file2);
        byte[] bufferClaro;
        byte[] buffer = new byte[1000]; //array de bytes
        //lee el fichero de 1k en 1k y pasa los fragmentos leidos al cifrador
        bytesLeidos = fe.read(buffer, 0, 1000);
        while (bytesLeidos != -1) {//mientras no se llegue al final del fichero
            //pasa texto cifrado al cifrador y lo descifra, asignándolo a bufferClaro
            bufferClaro = cifrador.update(buffer, 0, bytesLeidos);
            fs.write(bufferClaro); //Graba el texto claro en fichero
            bytesLeidos = fe.read(buffer, 0, 1000);
        }
        bufferClaro = cifrador.doFinal(); //Completa el descifrado
        fs.write(bufferClaro); //Graba el final del texto claro, si lo hay
        //cierra archivos
        fe.close();
        fs.close();
    }

    //método que muestra bytes
    public static void mostrarBytes(byte[] buffer) {
        System.out.write(buffer, 0, buffer.length);
    }
}

¿Cómo funciona RSA?

import java.io.IOException;
import java.security.*;
import javax.crypto.*;

//Encriptar y desencriptar un texto mediante clave pública RSA
public class CifradoRSA {

    public static void main(String[] args) throws Exception {

        System.out.println("Crear clave pública y privada");
        //Crea e inicializa el generador de claves RSA
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(512);//tamaño de la clave
        KeyPair clavesRSA = keyGen.generateKeyPair();
        PrivateKey clavePrivada = clavesRSA.getPrivate();//obtiene clave privada
        PublicKey clavePublica = clavesRSA.getPublic();//obtiene clave pública

        //muestra las claves generadas
        System.out.println("clavePublica: " + clavePublica);
        System.out.println("clavePrivada: " + clavePrivada);
        //texto a encriptar o cifrar
        byte[] bufferClaro = "Este es el mensaje secreto\n".getBytes();

        //Crea cifrador RSA
        Cipher cifrador = Cipher.getInstance("RSA");
        //Pone cifrador en modo ENCRIPTACIÓN utilizando la clave pública
        cifrador.init(Cipher.ENCRYPT_MODE, clavePublica);
        System.out.println("Cifrar con clave pública el Texto:");
        mostrarBytes(bufferClaro);

        //obtiene todo el texto cifrado
        byte[] bufferCifrado = cifrador.doFinal(bufferClaro);
        System.out.println("Texto CIFRADO");
        mostrarBytes(bufferCifrado); //muestra texto cifrado
        System.out.println("\n_______________________________");

        //Pone cifrador en modo DESENCRIPTACIÓN utilizando la clave privada
        cifrador.init(Cipher.DECRYPT_MODE, clavePrivada);
        System.out.println("Descifrar con clave privada");

        //obtiene el texto descifrado
        bufferClaro = cifrador.doFinal(bufferCifrado);
        System.out.println("Texto DESCIFRADO");
        mostrarBytes(bufferClaro);//muestra texto descifrado
        System.out.println("\n_______________________________");
    }

    public static void mostrarBytes(byte[] buffer) throws IOException {
        System.out.write(buffer);
    }
}

Proyecto en Intellij Idea de Criptografia

Uso en Kotlin:

Ejemplo de cifrado AES en Kotlin

Código de Cifrado AES en Kotlin

 

Programar un socket seguro:

Ejemplo: Servidor

Ejemplo: Cliente

 

Tarea de unidad 4

 

Más información:

Cifrado simétrico y asimétrico

Criptografía en Kotlin

Deja una respuesta