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

Java: Get rid of `Cipher.init()` overhead

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

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 方法的大部分时间,因为数据非常小。 IE。超过 1200 万次调用,Cipher.init() 平均需要 3 微秒,而 Cipher.doFinal() 平均需要 < 0.5 微秒。

我使用 JDK 1.8.0_73 并且我的处理器支持 AES-NI.

What takes so long in Cipher.init()?

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

Is there any way to speed up this code using Java only? For instance by taking advantage of the fact I will be decrypting always only a single block of data?

是的,但这需要重写 AES 算法的基本部分。您可以在 AESCrypt.java.

的 JDK 来源中找到它

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

Would it be faster to use a C/C++ implementation and call it using JNI? If so, is there any well-established library for that?

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