Saltar al contenido

¿Cómo utilizo el cifrado / descifrado 3DES en Java?

Hemos recabado en distintos espacios para así mostrarte la respuesta a tu problema, si continúas con inquietudes puedes dejarnos la inquietud y te responderemos con gusto.

Solución:

Su código estaba bien, excepto por el bit de codificación Base 64 (que mencionó que era una prueba), la razón por la que la salida puede no tener sentido es que estaba mostrando un byte sin procesar array (haciendo toString () en un byte array devuelve su referencia interna de Java, no la representación de cadena de la contenido). Aquí hay una versión que está un poco limpia y que imprime “kyle boon” como el decodificado string:

import java.security.MessageDigest;
import java.util.Arrays;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class TripleDESTest 

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

        String text = "kyle boon";

        byte[] codedtext = new TripleDESTest().encrypt(text);
        String decodedtext = new TripleDESTest().decrypt(codedtext);

        System.out.println(codedtext); // this is a byte array, you'll just see a reference to an array
        System.out.println(decodedtext); // This correctly shows "kyle boon"
    

    public byte[] encrypt(String message) throws Exception 
        final MessageDigest md = MessageDigest.getInstance("md5");
        final byte[] digestOfPassword = md.digest("HG58YZ3CR9"
                .getBytes("utf-8"));
        final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
        for (int j = 0, k = 16; j < 8;) 
            keyBytes[k++] = keyBytes[j++];
        

        final SecretKey key = new SecretKeySpec(keyBytes, "DESede");
        final IvParameterSpec iv = new IvParameterSpec(new byte[8]);
        final Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key, iv);

        final byte[] plainTextBytes = message.getBytes("utf-8");
        final byte[] cipherText = cipher.doFinal(plainTextBytes);
        // final String encodedCipherText = new sun.misc.BASE64Encoder()
        // .encode(cipherText);

        return cipherText;
    

    public String decrypt(byte[] message) throws Exception 
        final MessageDigest md = MessageDigest.getInstance("md5");
        final byte[] digestOfPassword = md.digest("HG58YZ3CR9"
                .getBytes("utf-8"));
        final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
        for (int j = 0, k = 16; j < 8;) 
            keyBytes[k++] = keyBytes[j++];
        

        final SecretKey key = new SecretKeySpec(keyBytes, "DESede");
        final IvParameterSpec iv = new IvParameterSpec(new byte[8]);
        final Cipher decipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
        decipher.init(Cipher.DECRYPT_MODE, key, iv);

        // final byte[] encData = new
        // sun.misc.BASE64Decoder().decodeBuffer(message);
        final byte[] plainText = decipher.doFinal(message);

        return new String(plainText, "UTF-8");
    

Aquí hay una solución usando el javax.crypto biblioteca y la biblioteca de códec de apache commons para codificar y decodificar en Base64:

import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import org.apache.commons.codec.binary.Base64;

public class TrippleDes 

    private static final String UNICODE_FORMAT = "UTF8";
    public static final String DESEDE_ENCRYPTION_SCHEME = "DESede";
    private KeySpec ks;
    private SecretKeyFactory skf;
    private Cipher cipher;
    byte[] arrayBytes;
    private String myEncryptionKey;
    private String myEncryptionScheme;
    SecretKey key;

    public TrippleDes() throws Exception 
        myEncryptionKey = "ThisIsSpartaThisIsSparta";
        myEncryptionScheme = DESEDE_ENCRYPTION_SCHEME;
        arrayBytes = myEncryptionKey.getBytes(UNICODE_FORMAT);
        ks = new DESedeKeySpec(arrayBytes);
        skf = SecretKeyFactory.getInstance(myEncryptionScheme);
        cipher = Cipher.getInstance(myEncryptionScheme);
        key = skf.generateSecret(ks);
    


    public String encrypt(String unencryptedString) 
        String encryptedString = null;
        try 
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] plainText = unencryptedString.getBytes(UNICODE_FORMAT);
            byte[] encryptedText = cipher.doFinal(plainText);
            encryptedString = new String(Base64.encodeBase64(encryptedText));
         catch (Exception e) 
            e.printStackTrace();
        
        return encryptedString;
    


    public String decrypt(String encryptedString) 
        String decryptedText=null;
        try 
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] encryptedText = Base64.decodeBase64(encryptedString);
            byte[] plainText = cipher.doFinal(encryptedText);
            decryptedText= new String(plainText);
         catch (Exception e) 
            e.printStackTrace();
        
        return decryptedText;
    


    public static void main(String args []) throws Exception
    
        TrippleDes td= new TrippleDes();

        String target="imparator";
        String encrypted=td.encrypt(target);
        String decrypted=td.decrypt(encrypted);

        System.out.println("String To Encrypt: "+ target);
        System.out.println("Encrypted String:" + encrypted);
        System.out.println("Decrypted String:" + decrypted);

    


La ejecución del programa anterior da como resultado el siguiente resultado:

String To Encrypt: imparator
Encrypted String:FdBNaYWfjpWN9eYghMpbRA==
Decrypted String:imparator

Pasé momentos difíciles para resolverlo por mí mismo y esta publicación me ayudó a encontrar la respuesta correcta para mi caso. Cuando se trabaja con mensajería financiera como ISO-8583, los requisitos de 3DES son bastante específicos, por lo que para mi caso especial, las combinaciones "DESede / CBC / PKCS5Padding" no resolvieron el problema. Después de algunas pruebas comparativas de mis resultados con algunas calculadoras 3DES diseñadas para el mundo financiero, encontré que el valor "DESede / ECB / Nopadding" es más adecuado para la tarea específica.

Aquí hay una implementación de demostración de mi clase TripleDes (usando el proveedor de Bouncy Castle)



    import java.security.InvalidKeyException;
    import java.security.NoSuchAlgorithmException;
    import java.security.NoSuchProviderException;
    import java.security.Security;
    import javax.crypto.BadPaddingException;
    import javax.crypto.Cipher;
    import javax.crypto.IllegalBlockSizeException;
    import javax.crypto.NoSuchPaddingException;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;


    /**
     *
     * @author Jose Luis Montes de Oca
     */
    public class TripleDesCipher 
       private static String TRIPLE_DES_TRANSFORMATION = "DESede/ECB/Nopadding";
       private static String ALGORITHM = "DESede";
       private static String BOUNCY_CASTLE_PROVIDER = "BC";
       private Cipher encrypter;
       private Cipher decrypter;

       public TripleDesCipher(byte[] key) throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,
             InvalidKeyException 
          Security.addProvider(new BouncyCastleProvider());
          SecretKey keySpec = new SecretKeySpec(key, ALGORITHM);
          encrypter = Cipher.getInstance(TRIPLE_DES_TRANSFORMATION, BOUNCY_CASTLE_PROVIDER);
          encrypter.init(Cipher.ENCRYPT_MODE, keySpec);
          decrypter = Cipher.getInstance(TRIPLE_DES_TRANSFORMATION, BOUNCY_CASTLE_PROVIDER);
          decrypter.init(Cipher.DECRYPT_MODE, keySpec);
       

       public byte[] encode(byte[] input) throws IllegalBlockSizeException, BadPaddingException 
          return encrypter.doFinal(input);
       

       public byte[] decode(byte[] input) throws IllegalBlockSizeException, BadPaddingException 
          return decrypter.doFinal(input);
       
    

Si haces scroll puedes encontrar las acotaciones de otros creadores, tú aún tienes la habilidad insertar el tuyo si lo crees conveniente.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

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