Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Performance optimizations #15

Closed
overheadhunter opened this issue Apr 30, 2020 · 0 comments
Closed

Performance optimizations #15

overheadhunter opened this issue Apr 30, 2020 · 0 comments
Milestone

Comments

@overheadhunter
Copy link
Member

overheadhunter commented Apr 30, 2020

We used to manually generate a keystream and XOR it with the plaintext.

While this implemenation was correct, easy to review (and actually reviewed in two independent audits), it is not necessary.

It got therefore replaced with an easy-to-use BouncyCastle high-level API in commit 620a9ad:

public byte[] computeCtr(byte[] input, byte[] key, byte[] iv) {
SICBlockCipher cipher = new SICBlockCipher(blockCipherSupplier.get());
CipherParameters params = new ParametersWithIV(new KeyParameter(key), iv);
cipher.init(true, params);
try {
byte[] output = new byte[input.length];
cipher.processBytes(input, 0, input.length, output, 0);
return output;
} catch (OutputLengthException e) {
throw new IllegalStateException("In CTR mode output length must be equal to input length", e);
}
}

Furthermore we added a JCE-based implementation in 90b8cb6:

public byte[] computeCtr(byte[] input, byte[] key, final byte[] iv) {
try {
Cipher cipher = threadLocalCipher.get();
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv));
return cipher.doFinal(input);
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
throw new IllegalArgumentException("Key or IV invalid.");
} catch (BadPaddingException e) {
throw new IllegalStateException("Cipher doesn't require padding.", e);
} catch (IllegalBlockSizeException e) {
throw new IllegalStateException("Block size irrelevant for stream ciphers.", e);
}
}

The immediate effect is a significant 20% speedup on JDK 8:

Benchmark                               Mode  Cnt   Score    Error  Units
SivModeBenchmark.benchmarkJce (old)     avgt    4  21,904 ± 10,101  us/op

Benchmark                               Mode  Cnt   Score   Error  Units
SivModeBenchmark.benchmarkJce (new)     avgt    4  17,327 ± 1,357  us/op

More importantly, this directly benefits from further optimizations in the JRE. With JDK 14 I get even faster computation times:

Benchmark                               Mode  Cnt   Score    Error  Units
SivModeBenchmark.benchmarkJce           avgt    4  11,586 ±  2,245  us/op

Benchmark results on CI server:
old vs new.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant