Where is the IV in Triple DES?

8.2k views Asked by At

I'm encrypt data using triple DES. It works fine, but I have a question.

Where can I see the initialization vector (IV)?

It's 3des encyption with BASE64Decoder.

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
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 sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class Crypter {

    Cipher ecipher;
    Cipher dcipher;

    Crypter(String as_Phrase)
            throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException {
        this.ecipher = Cipher.getInstance("DESede");
        this.dcipher = Cipher.getInstance("DESede");
        this.ecipher.init(1, getSecretKey(as_Phrase));
        this.dcipher.init(2, getSecretKey(as_Phrase));

    }

    public String encrypt(String as_valueToEncrypt)
            throws BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException, IOException {
        byte[] lbarr_utf8 = as_valueToEncrypt.getBytes("UTF8");
        byte[] lbarr_enc = this.ecipher.doFinal(lbarr_utf8);

        return new BASE64Encoder().encode(lbarr_enc);
    }

    public String decrypt(String as_valueToDecrypt)
            throws BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException, IOException {
        byte[] lbarr_enc = new BASE64Decoder().decodeBuffer(as_valueToDecrypt);

        byte[] lbarr_utf8 = this.dcipher.doFinal(lbarr_enc);

        return new String(lbarr_utf8, "UTF8");
    }

    private SecretKey getSecretKey(String as_Phrase)
            throws UnsupportedEncodingException {
        return new SecretKeySpec(as_Phrase.getBytes("UTF8"), "DESede");
    }
}
2

There are 2 answers

0
Artjom B. On BEST ANSWER

You can get the IV from the cipher:

ecipher.getIV();

The problem is that the IV is generated during init. Since you init in the constructor you would run into the problem of using the same IV for every encryption of different ciphertexts. It's always best to generate a new Cipher and init it for every encryption and decryption operation separately.

You use the DESede cipher which is actually DESede/ECB/PKCS5Padding. Note that the mode is ECB which doesn't use an IV. So the above call returns null. Although this is the default mode, it is not recommended. It's safer to use DESede/CBC/PKCS5Padding which actually uses an IV.

So when you decrypt in CBC mode you need to pass that IV in:

dcipher.init(2, new SecretKeySpec(key, "DESede"), new IvParameterSpec(ecipher.getIV()));

To reduce the burden of passing the IV around you could then append the IV to the front of the ciphertext before encoding it and slice it off before decrypting the ciphertext. DES is a 64-bit cipher so your IV will be 8 bytes long.

5
retroq On

Cipher has getIV() method, which returns initialization vector.