Criptografía de cifrado simétrico en Java

La criptografía es el estudio de diferentes técnicas para proteger los datos de una entidad no autorizada. En informática, tratamos de desarrollar estrategias y prácticas para proteger datos confidenciales. La mayor parte de la criptografía implica funciones matemáticas muy avanzadas que se utilizan para proteger los datos. El único propósito de los algoritmos desarrollados para criptografía es ocultar datos del atacante o intermediario. En este artículo, entenderemos el concepto en criptografía llamado cifrado simétrico. 
Antes de entrar en el concepto, primero comprendamos algunos términos clave relacionados con la criptografía. Están:
 

  • Texto sin formato: El texto sin formato es el mensaje o los datos originales que se ocultan a la vista mediante un algoritmo de cifrado criptográfico.
  • Texto cifrado: es el resultado de la operación de cifrado cuando se proporciona la clave y el texto sin formato. También son los datos alimentados a una función de descifrado.
  • Clave: la clave es un dato o un par de datos correlacionados cuando la entrada con texto sin formato en una función de cifrado produce texto cifrado. La clave debe estar protegida ya que el algoritmo está disponible públicamente. 
     
  • Sal: una sal es un dato aleatorio cuando se agrega a una función hash, proporciona aún más entropía en la salida, lo que hace que los ataques sucedan con menos probabilidad. Un buen hash criptográfico siempre debe usar sal.

Ahora, comprendamos las funciones de los componentes involucrados en la criptografía. 
 

  • Firma digital: Una firma digital es una función que verifica la autenticidad de un mensaje que llega de forma remota. Al firmar el mensaje con la clave privada, el uso de la clave pública para descifrar el mensaje confirma la autenticidad del remitente.
  • Cifrado: el cifrado es el proceso de tomar texto sin formato y convertirlo en un texto cifrado, que nuevamente se puede convertir a los datos originales con una clave adecuada en un momento posterior. Se logra con una clave compartida o un par de claves asimétricas.
  • Hashing: hashing nos permite mapear un conjunto de bytes de tamaño arbitrario en un tamaño finito de un conjunto de bytes relativamente único. Es una función matemática unidireccional para mapear datos.

Arquitectura de criptografía de Java
La JCA (Arquitectura de criptografía de Java) es el corazón y el alma del cifrado, descifrado, hashing, aleatorio seguro y varios otros motores de Java que nos permiten realizar funciones criptográficas con la programación de Java. Los siguientes son algunos conceptos básicos involucrados en esta arquitectura. 
 

  • Aleatorio seguro: este motor se utiliza para crear números aleatorios criptográficamente fuertes. Secure Random es un requisito esencial para las buenas operaciones criptográficas en Java. Se utiliza para semillas o llaves.
  • Resumen de mensajes: este motor se utiliza para producir hashes criptográficamente seguros. El resumen es una función hash que toma una entrada de longitud variable y produce una salida de longitud fija.
  • Firma: Es un motor para crear y validar firmas digitales. Las firmas digitales son únicas, toman una combinación de un hash y una operación asimétrica de cifrado de clave pública para crear un valor o firma único.
  • Cifrado: Es el motor para proporcionar operaciones de cifrado. Un cifrado proporciona soporte para operaciones asimétricas y simétricas. Un cifrado también admite cifrados de flujo y de bloque.

Cifrado: el cifrado es el proceso de ocultar datos de texto sin formato con el uso de una clave, que produce texto cifrado. El texto cifrado se vuelve difícil de leer sin la clave que se utilizó para generar ese texto cifrado. Solo las entidades autorizadas pueden leer el texto original. Entendamos los objetivos del cifrado. En las siguientes ilustraciones, estamos considerando «A» como el remitente y «B» como el receptor. 
 

  • Confidencialidad: también se conoce como privacidad, es decir, el mensaje que «A» envía a «B» solo puede ser leído por «B», suponiendo que el algoritmo y la clave son compartidos solo por «A» y «B». 
     

  • Integridad: los datos enviados por «A» deben recibir a «B» sin ninguna modificación por parte de un mal actor o ataques de intermediarios.
     

  • Autenticación: Es el proceso de verificar o reconocer la identidad del usuario mediante criptografía. Por ejemplo, si «A» envía un mensaje a «B», entonces la autenticidad prueba que el mensaje fue enviado solo por «A».
     

  • No repudio: Es una forma de probar que el mensaje vino de “A” y “B” puede creer que vino de “A” y “A” puede confirmar que lo envió.
     

Cifrado simétrico: el cifrado simétrico o el cifrado de clave compartida es un método de cifrado en el que ambas partes involucradas comparten una clave estándar. Esa clave común debe ser mantenida en secreto por ambas partes. Por ejemplo, «A» cifrará un mensaje con una clave compartida «K», luego «B» puede descifrar el mensaje cifrado solo con «K».
Cifrado asimétrico:El cifrado asimétrico o el cifrado de pares de claves pública/privada se basa en el concepto de dos claves relacionadas matemáticamente, es decir, una para cifrar y la otra para descifrar. Por ejemplo, «A» creará una clave pública y privada, y compartirá la clave pública con todos. Puede cifrar un mensaje con la clave privada y enviarlo a «B». “B” puede descifrar el mensaje utilizando la clave pública de “A”, que está abiertamente disponible. Si «B» quiere enviar un mensaje privado a «A», puede cifrar los datos usando la clave pública de «A» y «B» puede descifrarlos usando su clave privada.
Implementación del cifrado simétrico
Para implementar el cifrado simétrico, necesitamos una clave compartida. Generaremos una clave compartida, pero antes de eso, necesitamos conocer algunas clases y funciones. Están:
 

  1. Clase SecureRandom: esta clase ayuda a generar un número aleatorio seguro. Los siguientes son los detalles del constructor de la clase:
    • SecureRandom() construye un generador de números aleatorios seguros utilizando un algoritmo de números aleatorios predeterminado.
    • Public SecureRandom(byte[] seed) La instancia de SecureRandom se inicializa con los bytes de inicialización especificados. Los parámetros requeridos por este constructor son una semilla.
    • SecureRandom protegido (SecureRandomSpi secureRandomSpi, Proveedor proveedor). Los parámetros de este constructor son secureRandomSpi, que hace referencia a la implementación de SecureRandom. y proveedor que representa al proveedor.
    • getInstance(): Devuelve un objeto SecureRandom y aplica un algoritmo de generación de números aleatorios. La sintaxis de este método es: 
      <blockquote 
      public static SecureRandom getInstance(String algo) throws NoSuchAlgorithmException 
       
    • getProvider(): este método devuelve un objeto SecureRandom. La sintaxis de este método es: 
       

proveedor final público getProvider() 
 

  • getAlgorithm(): este método devuelve el nombre del algoritmo implementado por el objeto SecureRandom. La sintaxis de este método es: 
     

string pública getAlgorithm() 
 

  • setSeed(): este método reinicia el objeto aleatorio. La semilla dada se agrega, en lugar de reemplazar la semilla existente. Ayudando así a la aleatoriedad. La sintaxis de este método es: 
     

public void setSeed(byte[] semilla) 
 

  • getSeed(): este método devuelve el número dado de bytes de inicialización, calculados mediante el algoritmo de generación de inicialización. La sintaxis de este método es: 
     

byte estático público [] getSeed (int numBytes) 
 

  1. Clase KeyGenerator: esta clase proporciona la funcionalidad para el generador de claves. Los siguientes son los algoritmos KeyGenerator estándar con los tamaños de clave. 
    • AES (128)
    • DES (56)
    • DESede (168)
    • HmacSHA1
    • HmacSHA256

Enfoque para generar una clave simétrica: se pueden seguir los siguientes pasos para generar una clave simétrica. 
 

  • Cree una clave secreta usando la clase SecureRandom en Java que se usa para generar un número aleatorio. Esto se utilizará para cifrar y descifrar los datos. La clave secreta se puede crear como: 
     

// Creando el objeto 
SecureRandom random = new SecureRandom();
// Podemos invocar el siguiente método 
// para recuperar bytes aleatorios 
byte bytes[] = new byte[20]; 
aleatorio.nextBytes(bytes); 
 

  • La clase KeyGenerator proporcionará un método getInstance() que se puede usar para pasar una variable de string que denota el algoritmo de generación de claves. Devuelve un objeto KeyGenerator. Estamos usando el algoritmo AES aquí en este ejemplo. Esto se puede implementar como: 
     

KeyGenerator generador de claves = KeyGenerator.getInstance(AES); 
keygenerator.init(256, seguro al azar); 
 

  • Ahora, se genera la clave secreta y si deseamos ver realmente la clave generada, que es un objeto, podemos convertirla en formato hexadecimal usando DatatypeConverter.

A continuación se muestra la implementación del enfoque anterior:
 

Java

// Java program to generate
// a symmetric key
import java.security
    .SecureRandom;
 
import javax.crypto
    .KeyGenerator;
import javax.crypto.SecretKey;
import javax.xml.bind
    .DatatypeConverter;
 
// Class to create a
// symmetric key
public class symmetric {
 
    public static final String AES
        = "AES";
 
    // Function to create a secret key
    public static SecretKey createAESKey()
        throws Exception
    {
 
        // Creating a new instance of
        // SecureRandom class.
        SecureRandom securerandom
            = new SecureRandom();
 
        // Passing the string to
        // KeyGenerator
        KeyGenerator keygenerator
            = KeyGenerator.getInstance(AES);
 
        // Initializing the KeyGenerator
        // with 256 bits.
        keygenerator.init(256, securerandom);
        SecretKey key = keygenerator.generateKey();
        return key;
    }
 
    // Driver code
    public static void main(String args[])
        throws Exception
    {
        SecretKey Symmetrickey
            = createAESKey();
        System.out.println("Output");
        System.out.print("The Symmetric Key is :"
                         + DatatypeConverter.printHexBinary(
                               Symmetrickey.getEncoded()));
    }
}

Producción:
 

Cifrado y Descifrado usando la clave simétrica: Se pueden seguir los siguientes pasos para realizar el cifrado y descifrado. 
 

  • Cree el vector de inicialización que se requiere para evitar la repetición durante el proceso de cifrado. Esto es básicamente un número aleatorio.
  • La clase de cifrado proporciona dos funcionalidades, el cifrado y el descifrado. Se puede utilizar para especificar dos modos diferentes. 
     

Cifrado cifrado = Cipher.getInstance(“AES/CBC/PKCS5Padding”); 
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec); 
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec); 
 

  • Finalmente , se invoca el método doFinal() en cifrado que cifra o descifra datos en una operación de una sola parte, o finaliza una operación de varias partes y devuelve una array de bytes. 
     

doFinal(byte[] entrada)

A continuación se muestra la implementación del cifrado y descifrado simétrico. Aquí, estamos utilizando el algoritmo AES (ESTÁNDAR DE CIFRADO AVANZADO) para realizar el cifrado. 
 

Java

// Java program to implement the
// encryption and decryption
 
import java.security.SecureRandom;
import java.util.Scanner;
 
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec
    .IvParameterSpec;
import javax.xml.bind
    .DatatypeConverter;
 
// Creating the symmetric
// class which implements
// the symmetric
public class symmetric {
 
    private static final String AES
        = "AES";
 
    // We are using a Block cipher(CBC mode)
    private static final String AES_CIPHER_ALGORITHM
        = "AES/CBC/PKCS5PADDING";
 
    private static Scanner message;
 
    // Function to create a
    // secret key
    public static SecretKey createAESKey()
        throws Exception
    {
        SecureRandom securerandom
            = new SecureRandom();
        KeyGenerator keygenerator
            = KeyGenerator.getInstance(AES);
 
        keygenerator.init(256, securerandom);
        SecretKey key
            = keygenerator.generateKey();
 
        return key;
    }
 
    // Function to initialize a vector
    // with an arbitrary value
    public static byte[] createInitializationVector()
    {
 
        // Used with encryption
        byte[] initializationVector
            = new byte[16];
        SecureRandom secureRandom
            = new SecureRandom();
        secureRandom.nextBytes(initializationVector);
        return initializationVector;
    }
 
    // This function takes plaintext,
    // the key with an initialization
    // vector to convert plainText
    // into CipherText.
    public static byte[] do_AESEncryption(
        String plainText,
        SecretKey secretKey,
        byte[] initializationVector)
        throws Exception
    {
        Cipher cipher
            = Cipher.getInstance(
                AES_CIPHER_ALGORITHM);
 
        IvParameterSpec ivParameterSpec
            = new IvParameterSpec(
                initializationVector);
 
        cipher.init(Cipher.ENCRYPT_MODE,
                    secretKey,
                    ivParameterSpec);
 
        return cipher.doFinal(
            plainText.getBytes());
    }
 
    // This function performs the
    // reverse operation of the
    // do_AESEncryption function.
    // It converts ciphertext to
    // the plaintext using the key.
    public static String do_AESDecryption(
        byte[] cipherText,
        SecretKey secretKey,
        byte[] initializationVector)
        throws Exception
    {
        Cipher cipher
            = Cipher.getInstance(
                AES_CIPHER_ALGORITHM);
 
        IvParameterSpec ivParameterSpec
            = new IvParameterSpec(
                initializationVector);
 
        cipher.init(
            Cipher.DECRYPT_MODE,
            secretKey,
            ivParameterSpec);
 
        byte[] result
            = cipher.doFinal(cipherText);
 
        return new String(result);
    }
 
    // Driver code
    public static void main(String args[])
        throws Exception
    {
        SecretKey Symmetrickey
            = createAESKey();
 
        System.out.println(
            "The Symmetric Key is :"
            + DatatypeConverter.printHexBinary(
                  Symmetrickey.getEncoded()));
 
        byte[] initializationVector
            = createInitializationVector();
 
        String plainText
            = "This is the message "
              + "I want To Encrypt.";
 
        // Encrypting the message
        // using the symmetric key
        byte[] cipherText
            = do_AESEncryption(
                plainText,
                Symmetrickey,
                initializationVector);
 
        System.out.println(
            "The ciphertext or "
            + "Encrypted Message is: "
            + DatatypeConverter.printHexBinary(
                  cipherText));
 
        // Decrypting the encrypted
        // message
        String decryptedText
            = do_AESDecryption(
                cipherText,
                Symmetrickey,
                initializationVector);
 
        System.out.println(
            "Your original message is: "
            + decryptedText);
    }
}

Producción:
 

Publicación traducida automáticamente

Artículo escrito por nimma_shravan_kumar_reddy y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *