How do I use 3DES encryption/decryption in Java? How do I use 3DES encryption/decryption in Java? java java

How do I use 3DES encryption/decryption in Java?


Your code was fine except for the Base 64 encoding bit (which you mentioned was a test), the reason the output may not have made sense is that you were displaying a raw byte array (doing toString() on a byte array returns its internal Java reference, not the String representation of the contents). Here's a version that's just a teeny bit cleaned up and which prints "kyle boon" as the decoded 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");    }}


Here is a solution using the javax.crypto library and the apache commons codec library for encoding and decoding in 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);    }}

Running the above program results with the following output:

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


I had hard times figuring it out myself and this post helped me to find the right answer for my case. When working with financial messaging as ISO-8583 the 3DES requirements are quite specific, so for my especial case the "DESede/CBC/PKCS5Padding" combinations wasn't solving the problem. After some comparative testing of my results against some 3DES calculators designed for the financial world I found the the value "DESede/ECB/Nopadding" is more suited for the the specific task.

Here is a demo implementation of my TripleDes class (using the Bouncy Castle provider)

    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);       }    }