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

时间:2015-02-16 11:36:36

标签: 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)
  }

您看到生成密钥规范的缓慢操作已经处理完毕。但是,为每条消息调用init本身太慢了 我目前正在处理50K消息,调用init方法会增加近4秒。

有没有办法重新初始化一个不那么耗费时间的新IV?

1 个答案:

答案 0 :(得分:1)

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

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

你可以更新" (如Cipher.update(byte[])中所述)在加密之前使用随机块大小的字节数组(并且在解密时使用相同的块)。这与使用与IV相同的随机块几乎完全相同。

要看到这一点,请运行此代码段(使用上述方法生成完全相同的密文 - 但这只是为了与其他平台兼容,无需计算一个特定的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 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