1818import com .amazonaws .encryptionsdk .exception .BadCiphertextException ;
1919import java .security .GeneralSecurityException ;
2020import java .security .spec .AlgorithmParameterSpec ;
21+ import java .util .concurrent .ArrayBlockingQueue ;
2122import javax .annotation .concurrent .NotThreadSafe ;
2223import javax .crypto .Cipher ;
2324import javax .crypto .SecretKey ;
3334 */
3435@ NotThreadSafe
3536class 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