2

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");
    }
}
Artjom B.
  • 61,146
  • 24
  • 125
  • 222
  • It never occurred to you to look at the Javadocs for Cipher? – President James K. Polk Nov 28 '14 at 23:13
  • Pretty please with sugar on top, please use constants if they have been defined. Define your own if they haven't and use enums in new API's. `Cipher.ENCRYPT_MODE` is a lot more clear than `1` in the `init` method, don't you agree? – Maarten Bodewes Nov 30 '14 at 15:18

2 Answers2

6

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.

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
1

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

retroq
  • 572
  • 2
  • 7
  • 1
    This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post - you can always comment on your own posts, and once you have sufficient [reputation](http://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](http://stackoverflow.com/help/privileges/comment). – Kick Buttowski Nov 28 '14 at 22:55
  • 2
    @KickButtowski it is an answer, the question asks for how to get the IV, this answer gives a method that does exactly that. –  Nov 28 '14 at 23:07
  • It's an answer, but it isn't a good answer, as the code uses `"DESede"` without specifying the mode. On (almost) all runtimes this will default to ECB mode, which doesn't use an IV at all. – Maarten Bodewes Nov 30 '14 at 15:14
  • @owlstead that's right. That's why i've voted up another answer. But this would not have happened if author asked "why getIV returns null". – retroq Nov 30 '14 at 15:29
  • 1
    Yes, he just asked how to get IV, but it is important to also take the intent of the question into account. The code that uses ECB has not changed, as far as I can see. – Maarten Bodewes Nov 30 '14 at 15:33