i am having issues with java security. i have a bunch of bytes, and i want to split them into chunks of N bytes, encrypt them, and send them in separate (independant) messages.
here is my basic crypto stuff:
private byte[] generateIv(int size) {
byte[] iv = new byte[size];
randomSecureRandom.nextBytes(iv);
return iv;
}
@Override
public byte[] encryptData(byte[] iv, byte[] in, Key key) throws CryptoException {
try {
Cipher c = Cipher.getInstance("AES/CTR/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
return c.doFinal(in);
} catch (Exception ex) {
throw new CryptoException(ex);
}
}
@Override
public byte[] decryptData(byte[] iv, byte[] in, Key key) throws CryptoException {
try {
Cipher c = Cipher.getInstance("AES/CTR/PKCS5Padding");
c.init(Cipher.DECRYPT_MODE,key, new IvParameterSpec(iv));
return c.doFinal(in);
} catch(Exception ex) {
throw new CryptoException(ex);
}
}
@Override
public byte[] createHMAC(byte[] pauload, Key sigKey) throws CryptoException {
try {
Mac mac = Mac.getInstance("HMACSHA256");
mac.init(sigKey);
byte[] digest = mac.doFinal(pauload);
return digest;
} catch (Exception e) {
throw new CryptoException("unable to create HMAC",e);
}
}
i create the message like this (an AES-128 session key is generated in an initial handshake):
byte[] iv = generateIv();
byte[] hmac = createHMAC (inputBytes,key);
byte[] enc = encryptData(iv,inputBytes,key);
then i write in the message:
[iv bytes][enc bytes][hmac bytes]
on the opposite side, i do:
byte[] iv = readFirstEightBytes(inputBytes);
byte[] dec = decryptData(iv,inputBytes[8..N+8],key);
byte[] hmac = createHMAC(dec,inputBytes[N+9..end],key);
// compare hmac
return dec;
this works all nice and fluffy, except when i start to hammer it, it kind of tends to be really, really, slow. and my hotspots are:
encryptData 27%
createHMAC 22%
decryptData 18%
i was wondering if i'm being naive here? am i missing something obvious? i was wondering if i should maybe not get a fresh Cipher instance every time ... but i got a lot of concurrency, i am guessing that trying to make sharing an instance threadsafe is probably also not ideal ...
i see lots of room for improvement in the rest of my code, so this would make the encryption part look even worse.
who's got thoughts? or is 20 mb/s total throughput as good as it gets (on a modern, beefy laptop)?