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

0 投票
最新提问 用户: (120 分)

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?

发表于 用户: (420 分)
depending on your used crypto primitives/your crypto library you can simply prepend the IV to the ciphertext... in that case leave the IV all zero for decryption and skip block 1 of your result ...
发表于 用户: (1.2k 分)
Since you don't have an actual problem with your code, this question should either go to Cryptography or Code Review.
发表于 用户: (1.2k 分)
I'm voting to close this question as off-topic because this is not really a programming question. At its heart, it's a crypto question.
发表于 用户: (120 分)
Fair enough, I guess its borderline, as its partly about the general cryptography operation and partly about the correctness of the above implementation and how to handle the case with javax.crypto -classes. There isn't even a Java-tag in Cryptography, so it seems to be out of place there as well.

1个回答

0 投票
最新回答 用户: (2.1k 分)

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.

欢迎来到 Security Q&A ,有什么不懂的可以尽管在这里提问,你将会收到社区其他成员的回答。
...