Java:摆脱`Cipher.init()`开销

时间:2016-03-03 17:11:41

标签: java performance encryption aes

我需要提高以下方法的性能:

private byte[] decrypt(final byte[] encrypted, final Key key) throws ... {
    this.cipher.init(Cipher.DECRYPT_MODE, key);
    return this.cipher.doFinal(encrypted);
}

cipher对象(“AES / ECB / NoPadding”)在构造函数中初始化,因此可以重用它。使用ECB,因为encrypted数组将始终只包含16个字节的数据(即1个数据块)。使用128位密钥。

这种方法被称为数百万次,用于解密16字节块,每次使用不同的密钥。例如。这个方法就像这样调用:

final List<Key> keys = List with millions of keys
final byte[] data = new byte[] { ... 16 bytes of data go here ...}

for (final Key key : keys) {
    final byte[] encrypted = decrypt(data, key);

    // Do something with encrypted
}

Cipher.init()占用decrypt方法的大部分时间,因为数据太小。即如果调用次数超过1200万次,Cipher.init()平均需要3微秒,而Cipher.doFinal()需要&lt; 1 {}平均0.5微秒。

  • Cipher.init()
  • 需要多长时间
  • 有没有办法只使用Java来加速这段代码?例如,通过利用我将解密总是只有一个数据块的事实?
  • 使用C / C ++实现并使用JNI调用它会更快吗?如果是这样,那有没有完善的图书馆?

我使用的是JDK 1.8.0_73,我的处理器支持AES-NI。

1 个答案:

答案 0 :(得分:6)

  

在Cipher.init()中花了这么长时间?

在初始化期间,用户提供的密钥数据将扩展为加密和解密例程使用的会话密钥。

  

有没有办法只使用Java来加速这段代码?例如,通过利用我将解密总是只有一个数据块的事实?

是的,但这需要重写AES算法的基本部分。您可以在AESCrypt.java中的JDK源代码中找到它。

或者,您可以存储预初始化密码列表而不是密钥。

  

使用C / C ++实现并使用JNI调用它会更快吗?如果是这样,那有没有完善的图书馆?

很有可能,是的。 libcrypto这是OpenSSL的一部分将有所帮助。 Here is an example