Skip to content

Commit 28b1348

Browse files
committed
perf: avoid expensive call to Cipher.getInstance
1 parent 3191970 commit 28b1348

File tree

1 file changed

+32
-11
lines changed

1 file changed

+32
-11
lines changed

src/main/java/com/amazonaws/encryptionsdk/internal/CipherHandler.java

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import com.amazonaws.encryptionsdk.exception.BadCiphertextException;
1919
import java.security.GeneralSecurityException;
2020
import java.security.spec.AlgorithmParameterSpec;
21+
import java.util.concurrent.ArrayBlockingQueue;
2122
import javax.annotation.concurrent.NotThreadSafe;
2223
import javax.crypto.Cipher;
2324
import javax.crypto.SecretKey;
@@ -33,10 +34,12 @@
3334
*/
3435
@NotThreadSafe
3536
class CipherHandler {
37+
//TODO how to sze this, or allow it to be configured externally
38+
private static final CipherPool CIPHER_POOL = new CipherPool(32);
39+
3640
private final int cipherMode_;
3741
private final SecretKey key_;
3842
private final CryptoAlgorithm cryptoAlgorithm_;
39-
private final Cipher cipher_;
4043

4144
/**
4245
* Process data through the cipher.
@@ -62,16 +65,19 @@ public byte[] cipherData(
6265
final AlgorithmParameterSpec spec =
6366
new GCMParameterSpec(cryptoAlgorithm_.getTagLen() * 8, nonce, 0, nonce.length);
6467

68+
final Cipher cipher = CIPHER_POOL.borrowCipher();
6569
try {
66-
cipher_.init(cipherMode_, key_, spec);
70+
cipher.init(cipherMode_, key_, spec);
6771
if (contentAad != null) {
68-
cipher_.updateAAD(contentAad);
72+
cipher.updateAAD(contentAad);
6973
}
7074
} catch (final GeneralSecurityException gsx) {
7175
throw new AwsCryptoException(gsx);
7276
}
7377
try {
74-
return cipher_.doFinal(content, off, len);
78+
byte[] bytes = cipher.doFinal(content, off, len);
79+
CIPHER_POOL.returnCipher(cipher);
80+
return bytes;
7581
} catch (final GeneralSecurityException gsx) {
7682
throw new BadCiphertextException(gsx);
7783
}
@@ -90,15 +96,30 @@ public byte[] cipherData(
9096
this.cipherMode_ = cipherMode;
9197
this.key_ = key;
9298
this.cryptoAlgorithm_ = cryptoAlgorithm;
93-
this.cipher_ = buildCipherObject(cryptoAlgorithm);
9499
}
95100

96-
private static Cipher buildCipherObject(final CryptoAlgorithm alg) {
97-
try {
98-
// Right now, just GCM is supported
99-
return Cipher.getInstance("AES/GCM/NoPadding");
100-
} catch (final GeneralSecurityException ex) {
101-
throw new IllegalStateException("Java does not support the requested algorithm", ex);
101+
private static class CipherPool {
102+
private final ArrayBlockingQueue<Cipher> pool;
103+
104+
CipherPool(int size) {
105+
this.pool = new ArrayBlockingQueue<>(size);
106+
}
107+
108+
Cipher borrowCipher() {
109+
Cipher cipher = pool.poll();
110+
if (cipher == null) {
111+
try {
112+
// Right now, just GCM is supported
113+
cipher = Cipher.getInstance("AES/GCM/NoPadding");
114+
} catch (final GeneralSecurityException ex) {
115+
throw new IllegalStateException("Java does not support the requested algorithm", ex);
116+
}
117+
}
118+
return cipher;
119+
}
120+
121+
void returnCipher(Cipher cipher) {
122+
pool.offer(cipher);
102123
}
103124
}
104125
}

0 commit comments

Comments
 (0)