Java加密,重置IV可以提高性能吗?

标签 java performance scala encryption

我创建一个加密密码如下(在 Scala 中,使用 bouncy-caSTLe)

  def encryptCipher(secret:SecretKeySpec, iv:IvParameterSpec):Cipher = {
    val e = Cipher.getInstance("AES/GCM/NoPadding")
    e.init(Cipher.ENCRYPT_MODE, secret, iv)
  }

您会看到生成 key 规范的缓慢操作已经得到处理。然而,为每条消息调用 init 本身太慢。
我当前正在处理 50K 消息,调用 init 方法会增加近 4 秒。

有没有一种方法可以用一个新的 IV 来重新初始化,而不那么耗时?

最佳答案

标准库中没有标准方法可以做到这一点, 但如果您使用 AES,有一个很好的解决方法:

IV的目的是消除相同明文加密成相同密文的可能性。

您可以在加密之前使用随机 block 大小的字节数组“更新”(如Cipher.update(byte[]))(在解密时使用相同的 block )。这与使用与 IV 相同的随机 block 几乎完全相同。

要看到这一点,请运行此代码段(它使用上述方法生成完全相同相同的密文 - 但这只是为了与其他平台兼容,无需计算特定的 IV 即可确保安全。

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecureRandom secureRandom = new SecureRandom();

byte[] keyBytes = new byte[16];
secureRandom.nextBytes(keyBytes);
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");

byte[] plain = new byte[256];
secureRandom.nextBytes(plain);

// first init using random IV (save it for later)
cipher.init(Cipher.ENCRYPT_MODE, key, secureRandom);
byte[] realIv = cipher.getIV();
byte[] expected = cipher.doFinal(plain);

// now init using dummy IV and encrypt with real IV prefix
IvParameterSpec nullIv = new IvParameterSpec(new byte[16]);
cipher.init(Cipher.ENCRYPT_MODE, key, nullIv);
// calculate equivalent iv
Cipher equivalentIvAsFirstBlock = Cipher.getInstance("AES/CBC/NoPadding");
equivalentIvAsFirstBlock.init(Cipher.DECRYPT_MODE, key, nullIv);
byte[] equivalentIv = equivalentIvAsFirstBlock.doFinal(realIv);

cipher.update(equivalentIv);
byte[] result = cipher.doFinal(plain);
System.out.println(Arrays.equals(expected, result));

解密部分更容易,因为 block 解密的结果与之前的密文进行异或(参见 Block cipher mode of operation ),您只需将真实的 IV 附加到密文中,然后将其抛出:

// Encrypt as before

IvParameterSpec nullIv = new IvParameterSpec(new byte[16]);
cipher.init(Cipher.DECRYPT_MODE, key, nullIv);

cipher.update(realIv);
byte[] result = cipher.doFinal(encrypted);
// result.length == plain.length + 16
// just throw away the first block

关于Java加密,重置IV可以提高性能吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28540565/

相关文章:

java - 使用 java 8 流查找 2 个列表中匹配的元素并从另一个列表更新一个列表值

java.rmi.UnmarshalException : java. lang.ClassNotFoundException。无法使用 RMI 从另一个物理 JVM 访问类

java - 排名变量、排序

javascript - 如何在 React 中防止过多的 JS 事件处理程序?

scala - 在 Play 中以编程方式获取路线!框架 2.5.x

multithreading - Scala:WAITING列表被填充

scala - Spark – 连接第一行匹配条件

java - 能否使用 fork/join 跨线程边界安全地移植非线程安全值?

java - str.equals ("String") 与 "String".equals(str)

mysql - Rails 数据库性能调优