使用TripleDES加密时,将初始化向量(IV)附加到加密字节

时间:2017-05-16 15:04:37

标签: java scala security encryption initialization-vector

我想要将加密的令牌发送到客户端,并且我使用javax.crypto.Cipher进行加密。根据我的阅读,不建议使用ECB作为加密模式,因此我使用CBC初始化矢量和TripleDES作为密码方法。根据我的理解,有几点是正确的。

  1. 更重要的是,IV是随机的,并且每次加密都会初始化一个新的,而不是保密。
  2. 必须使用相同的IV来加密和解密令牌。
  3. 没有标准的方法来存储IV值,每个实现在这方面都可能有所不同。
  4. 因此,对于那些真实,我通过将附加的IV存储到加密的字节数组中来实现我的实现,并且在解密阶段,从字节数组中切割IV并用于解密。以下是Scala代码,但它在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)
    }
    

    此外,字节数组被编码/解码 org.apache.commons.codec.binary.Base64.encodeBase64String / decodeBase64在发送给客户端之前。

    所以我的问题是,这种方法存在什么错误或危险,你将IV存储在存储加密字符串的同一字节数组中?是否有更好的替代方案来存储IV:s?

1 个答案:

答案 0 :(得分:3)

IV的唯一目的是防止攻击者能够使用密文中的模式来推断有关明文的信息(参见semantic security),确保用相同的密钥加密的两个相同的明文将会对于不同的IV,具有显着不同的密文。

攻击者不知道密钥从IV中获得任何东西,因为IV在实际加密操作之前使用,并且在解密操作之后(通常;我不能想到任何使用的密码或模式)不同的IV,但它们可能存在。但是CBC的DES绝对不是其中之一。因此,将IV包含在密文中是没有害处的,将IV附加到密文是一种非常常见的做法。