Java:摆脱`Cipher.init()`开销
我需要提高以下方法的性能:
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 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.doFinal()
平均需要3微秒,而Cipher.doFinal()
平均需要<0.5微秒。
- 在
Cipher.init()
需要这么长时间? - 有没有办法只使用Java来加速这段代码? 例如,通过利用我将解密总是只有一个数据块的事实?
- 使用C / C ++实现并使用JNI调用它会更快吗? 如果是这样,那有没有完善的图书馆?
我使用JDK 1.8.0_73,我的处理器支持AES-NI。
在Cipher.init()中需要这么长时间?
在初始化期间,用户提供的密钥数据被扩展为加密和解密例程使用的会话密钥。
有没有办法只使用Java来加速这段代码? 例如,通过利用我将解密总是只有一个数据块的事实?
是的,但这需要重写AES算法的基本部分。 您可以在AESCrypt.java中的JDK源代码中找到它。
或者,您可以存储预初始化密码列表而不是密钥。
使用C / C ++实现并使用JNI调用它会更快吗? 如果是这样,那有没有完善的图书馆?
最有可能的是,是的。 libcrypto
是OpenSSL的一部分将有所帮助。 这是一个例子 。