java - 将 IV 作为最终 block 添加到加密的字节数组中

标签 java security encryption initialization-vector

我正在尝试将用于加密我的数据的 16 位 IV 添加为用于保存加密数据的字节数组中的最后一个 block 。我显然想为解密部分执行此操作,以便我可以为每个加密/解密调用使用完全随机的 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. 使用十六进制编码字节数组

解密步骤列表是:

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

我的方法有效,但我想我想知道的是,是否有“更好”的方法来做到这一点?我的意思是,是否有一套或更简单的方法来使用 Cipher* 类型来执行此操作?我找不到它们。

谢谢。

最佳答案

好吧,您当然可以避免冗长的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 两次。

关于java - 将 IV 作为最终 block 添加到加密的字节数组中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18234234/

相关文章:

Android 设备管理员 - 禁用未应用于(多用户) guest 帐户的相机

wcf - 保护 WCF 使用的命名管道

ios - Swift 3 中 SecKeyCreateEncryptedData 和 SecKeyEncrypt 的区别

java - 在网络上传递 Swing 类(引用)?

java - 如何列出字符串中的所有提及

java - 在 Java 6 中用于并发访问列表的最佳方法

encryption - RSA解密抛出 'Access denied'异常

java - 方法链 + 继承不能很好地结合在一起?

javascript - 使用 parse.com 的云函数安全性

java - 加密Java代码转Go代码