将IV添加到加密字节数组作为最终块

时间:2013-08-14 14:16:59

标签: java security encryption initialization-vector

我正在尝试将用于加密数据的16位IV添加为用于保存加密数据的字节数组中的最后一个块。我想明确地为解密部分做这个,这样我就可以为每个加密/解密调用使用完全随机的IV。我有以下用于测试目的:

public static String encrypt(String plainText) throws Exception {
   encryptionKey = new SecretKeySpec(eKey.getBytes("UTF-8"), "AES");

   cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
   cipher.init(Cipher.ENCRYPT_MODE, encryptionKey, initialisationVector);

   byte[] eDataAndIv = appendIvToEncryptedData(cipher.doFinal(plainText.getBytes("UTF-8")), initialisationVector.getIV());
   return bytesToHexString(eDataAndIv);
}

public static String decrypt(String hexEncoded) throws Exception {
   byte[] decodedBytes = hexStringToBytes(hexEncoded);

   ArrayList<byte[]> al = retreiveIvFromByteArray(decodedBytes);
   byte[] eData = al.get(0);
   byte[] iv = al.get(1);

   cipher.init(Cipher.DECRYPT_MODE, encryptionKey, new IvParameterSpec(iv));
   return reconstructedPlainText(cipher.doFinal(eData));
}

private static byte[] appendIvToEncryptedData(byte[] eData, byte[] iv) throws Exception {
   ByteArrayOutputStream os = new ByteArrayOutputStream();
   os.write(eData);
   os.write(iv);
   return os.toByteArray();
}

private static ArrayList<byte[]> retreiveIvFromByteArray(byte[] dataPlusIv) {
   ByteArrayOutputStream iv = new ByteArrayOutputStream(16);
   ByteArrayOutputStream eData = new ByteArrayOutputStream();

   iv.write(dataPlusIv, dataPlusIv.length - 16, 16);
   eData.write(dataPlusIv, 0, dataPlusIv.length - 16);

   ArrayList<byte[]> al = new ArrayList<byte[]>();
   al.add(eData.toByteArray());
   al.add(iv.toByteArray());

   return al;
}

加密步骤列表如下:

  1. 创建IV
  2. 加密数据
  3. 将IV附加到加密数据字节数组的末尾
  4. 使用十六进制编码字节数组
  5. 解密步骤列表如下:

    1. 解码十六进制
    2. 从字节数组中断加密数据和IV
    3. 使用IV
    4. 解密数据

      我的作品有哪些,但我想我想知道的是,有没有“更好”的方法呢?我的意思是,使用Cipher*类型是否有一套或更简单的方法来做到这一点?我找不到他们。

      感谢。

1 个答案:

答案 0 :(得分:3)

嗯,你当然可以避免冗长的retreiveIvFromByteArray代码:

public static String decrypt(String hexEncoded) throws Exception {
   byte[] decodedBytes = hexStringToBytes(hexEncoded);
   int ivIndex = decodedBytes.length - 16;
   cipher.init(Cipher.DECRYPT_MODE, encryptionKey,
       new IvParameterSpec(decodedBytes, ivIndex, 16));
   return reconstructedPlainText(cipher.doFinal(decodedBytes, 0, ivIndex));
}

这是你想到的那种吗?

同样对于appendIvToEncryptedData,你可以创建一个适当长度的新字节数组,并使用System.arraycopy两次。