Search code examples
javascalasecurityencryptioninitialization-vector

Appending the initialization vector (IV) to the encrypted bytes when encrypting with TripleDES


I'm wanting to deliver an encrypted token to the client, and I'm using the javax.crypto.Cipher for encryption. From what I've read, ECB as the encryption mode isn't recommended, so I am using CBC with an initialization vector and TripleDES as the cipher method. To my understanding, there are few points that hold true.

  1. It is more important that the IV is random and that a new one is initialized with every encryption rather than that it is kept secret.
  2. Same IV must be used for encrypting and decrypting the token.
  3. There is no standard way to store the IV values, and each implementation can differ in that regard.

So with those true, I did my implementation with storing the IV appended to the encrypted byte array, and in decryption phase the IV is cut from the byte array and used for decryption. Following is in Scala code, but it wouldn't differ much in Java.

val algorithmName = "TripleDES"
def encrypt(bytes: Array[Byte], secret: String): Array[Byte] = {
  val secretKey = new SecretKeySpec(secret.getBytes("UTF-8"), algorithmName)
  val encipher = Cipher.getInstance(algorithmName + "/CBC/PKCS5Padding")
  val iv = encipher.getParameters.getParameterSpec(classOf[IvParameterSpec])
  encipher.init(Cipher.ENCRYPT_MODE, secretKey, iv)
  encipher.doFinal(bytes) ++ iv.getIV
}

def decrypt(bytes: Array[Byte], secret: String): Array[Byte] = {
  val secretKey = new SecretKeySpec(secret.getBytes("UTF-8"), algorithmName)
  val encipher = Cipher.getInstance(algorithmName + "/CBC/PKCS5Padding")
  val ivIndex = bytes.length - 8
  val iv = new IvParameterSpec(bytes, ivIndex, 8)
  encipher.init(Cipher.DECRYPT_MODE, secretKey, iv)
  encipher.doFinal(bytes, 0, ivIndex)
}

Furthermore array of bytes is encoded/decoded with org.apache.commons.codec.binary.Base64.encodeBase64String / decodeBase64 before sending to the client.

So my question is, is there anything wrong or dangerous with this kind of approach where you store the IV in the same byte array as you store the encrypted string? Is there a better alternative to storing the IV:s?


Solution

  • The sole purpose of the IV is to prevent attackers from being able to use patterns in the ciphertext to infer information about the plaintext (see semantic security) by ensuring that two identical plaintexts, enciphered with the same key, will have significantly different ciphertexts for different IVs.

    An attacker who does not know the key gains nothing from the IV, as the IV is used before the actual encryption operation, and after the decryption operation (typically; I can't think of any cipher or mode that uses the IV differently, but they might exist. DES with CBC is definitely not one of those, though). Therefore, there is no harm in including your IV with your ciphertext, and appending the IV to the ciphertext is an extremely common practice.