I need to increase performance of the following method:
private byte[] decrypt(final byte[] encrypted, final Key key) throws ... {
this.cipher.init(Cipher.DECRYPT_MODE, key);
return this.cipher.doFinal(encrypted);
}
The cipher
object ("AES/ECB/NoPadding") is initialized in the constructor, so that it can be reused. ECB is used since the encrypted
array will contain always only 16 bytes of data (i.e. 1 block of data). 128 bit key is used.
This method is called millions of times to decrypt 16 byte chunk, each time with a different key. E.g. the method is called like this:
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
}
The Cipher.init()
takes most of the time of the decrypt
method, since the data is so small. I.e. with over 12 million invocations, Cipher.init()
takes 3 microseconds on average while Cipher.doFinal()
takes < 0.5 microseconds on average.
Cipher.init()
?I use JDK 1.8.0_73 and my processor supports AES-NI.
What takes so long in Cipher.init()?
During initialization a user-supplied key data is expanded into session keys used by encryption and decryption routines.
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?
Yes, but this would require rewriting the essential part of AES algorithm. You may find it in JDK sources in AESCrypt.java.
Alternatively, you may store a list of preinitialized Ciphers instead of Keys.
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?
Most likely, yes. libcrypto
which is a part of OpenSSL will help. Here is an example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With