Author: schultz
Date: Sun Nov 25 15:49:28 2018
New Revision: 1847417

URL: http://svn.apache.org/viewvc?rev=1847417&view=rev
Log:
Add support for GCM block cipher mode.

Modified:
    
tomcat/trunk/java/org/apache/catalina/tribes/group/interceptors/EncryptInterceptor.java
    
tomcat/trunk/test/org/apache/catalina/tribes/group/interceptors/TestEncryptInterceptor.java
    tomcat/trunk/webapps/docs/changelog.xml

Modified: 
tomcat/trunk/java/org/apache/catalina/tribes/group/interceptors/EncryptInterceptor.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/tribes/group/interceptors/EncryptInterceptor.java?rev=1847417&r1=1847416&r2=1847417&view=diff
==============================================================================
--- 
tomcat/trunk/java/org/apache/catalina/tribes/group/interceptors/EncryptInterceptor.java
 (original)
+++ 
tomcat/trunk/java/org/apache/catalina/tribes/group/interceptors/EncryptInterceptor.java
 Sun Nov 25 15:49:28 2018
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentLi
 
 import javax.crypto.Cipher;
 import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.GCMParameterSpec;
 import javax.crypto.spec.IvParameterSpec;
 import javax.crypto.spec.SecretKeySpec;
 
@@ -64,7 +65,7 @@ public class EncryptInterceptor extends
     private String encryptionKeyString;
 
 
-    private EncryptionManager encryptionManager;
+    private BaseEncryptionManager encryptionManager;
 
     public EncryptInterceptor() {
     }
@@ -300,7 +301,7 @@ public class EncryptInterceptor extends
         return result;
     }
 
-    private static EncryptionManager createEncryptionManager(String algorithm,
+    private static BaseEncryptionManager createEncryptionManager(String 
algorithm,
             byte[] encryptionKey, String providerName)
         throws NoSuchAlgorithmException, NoSuchPaddingException, 
NoSuchProviderException {
         if(null == encryptionKey)
@@ -328,29 +329,31 @@ public class EncryptInterceptor extends
         }
 
         // Note: ECB is not an appropriate mode for secure communications.
+        if("GCM".equalsIgnoreCase(algorithmMode))
+            return new GCMEncryptionManager(algorithm, new 
SecretKeySpec(encryptionKey, algorithmName), providerName);
+
         if(!("CBC".equalsIgnoreCase(algorithmMode)
                 || "OFB".equalsIgnoreCase(algorithmMode)
                 || "CFB".equalsIgnoreCase(algorithmMode)))
             throw new 
IllegalArgumentException(sm.getString("encryptInterceptor.algorithm.unsupported-mode",
 algorithmMode));
 
-        EncryptionManager mgr = new EncryptionManager(algorithm,
+        BaseEncryptionManager mgr = new BaseEncryptionManager(algorithm,
                 new SecretKeySpec(encryptionKey, algorithmName),
                 providerName);
 
         return mgr;
     }
 
-    private static class EncryptionManager {
+    private static class BaseEncryptionManager {
         /**
          * The fully-specified algorithm e.g. AES/CBC/PKCS5Padding.
          */
         private final String algorithm;
 
         /**
-         * The size of the initialization vector to use for encryption. This is
-         * often, but not always, the same as the block size.
+         * The block size of the cipher.
          */
-        private final int ivSize;
+        private final int blockSize;
 
         /**
          * The cryptographic provider name.
@@ -375,7 +378,7 @@ public class EncryptInterceptor extends
          */
         private final ConcurrentLinkedQueue<SecureRandom> randomPool;
 
-        public EncryptionManager(String algorithm, SecretKeySpec secretKey, 
String providerName)
+        public BaseEncryptionManager(String algorithm, SecretKeySpec 
secretKey, String providerName)
             throws NoSuchAlgorithmException, NoSuchPaddingException, 
NoSuchProviderException {
             this.algorithm = algorithm;
             this.providerName = providerName;
@@ -383,7 +386,7 @@ public class EncryptInterceptor extends
 
             cipherPool = new ConcurrentLinkedQueue<>();
             Cipher cipher = createCipher();
-            ivSize = cipher.getBlockSize();
+            blockSize = cipher.getBlockSize();
             cipherPool.offer(cipher);
             randomPool = new ConcurrentLinkedQueue<>();
         }
@@ -402,8 +405,14 @@ public class EncryptInterceptor extends
             return secretKey;
         }
 
-        private int getIVSize() {
-            return ivSize;
+        /**
+         * Gets the size of the initialization vector for the cipher being 
used.
+         * The IV size is often, but not always, the block size for the cipher.
+         *
+         * @return The size of the initialization vector for this algorithm.
+         */
+        protected int getIVSize() {
+            return blockSize;
         }
 
         private String getProviderName() {
@@ -474,7 +483,7 @@ public class EncryptInterceptor extends
 
             try {
                 cipher = getCipher();
-                cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(), 
generateIV(iv, 0, ivSize));
+                cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(), 
generateIV(iv, 0, getIVSize()));
 
                 // Prepend the IV to the beginning of the encrypted data
                 byte[][] data = new byte[2][];
@@ -500,6 +509,7 @@ public class EncryptInterceptor extends
         private byte[] decrypt(byte[] bytes) throws GeneralSecurityException {
             Cipher cipher = null;
 
+            int ivSize = getIVSize();
             AlgorithmParameterSpec IV = generateIV(bytes, 0, ivSize);
 
             try {
@@ -539,4 +549,22 @@ public class EncryptInterceptor extends
             return new IvParameterSpec(ivBytes, offset, length);
         }
     }
+
+    private static class GCMEncryptionManager extends BaseEncryptionManager
+    {
+        public GCMEncryptionManager(String algorithm, SecretKeySpec secretKey, 
String providerName)
+                throws NoSuchAlgorithmException, NoSuchPaddingException, 
NoSuchProviderException {
+            super(algorithm, secretKey, providerName);
+        }
+
+        @Override
+        protected int getIVSize() {
+            return 12;
+        }
+
+        @Override
+        protected AlgorithmParameterSpec generateIV(byte[] bytes, int offset, 
int length) {
+            return new GCMParameterSpec(128, bytes, offset, length);
+        }
+    }
 }

Modified: 
tomcat/trunk/test/org/apache/catalina/tribes/group/interceptors/TestEncryptInterceptor.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/tribes/group/interceptors/TestEncryptInterceptor.java?rev=1847417&r1=1847416&r2=1847417&view=diff
==============================================================================
--- 
tomcat/trunk/test/org/apache/catalina/tribes/group/interceptors/TestEncryptInterceptor.java
 (original)
+++ 
tomcat/trunk/test/org/apache/catalina/tribes/group/interceptors/TestEncryptInterceptor.java
 Sun Nov 25 15:49:28 2018
@@ -255,7 +255,6 @@ public class TestEncryptInterceptor {
     }
 
     @Test
-    @Ignore("GCM mode is unsupported because it requires a custom 
initialization vector")
     public void testGCM() throws Exception {
         src.setEncryptionAlgorithm("AES/GCM/PKCS5Padding");
         src.start(Channel.SND_TX_SEQ);

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1847417&r1=1847416&r2=1847417&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Sun Nov 25 15:49:28 2018
@@ -163,6 +163,9 @@
         Make EncryptInterceptor thread-safe. This makes this interceptor
         actually usable. (schultz/markt)
       </fix>
+      <add>
+        Add support for GCM mode to EncryptInterceptor. (schultz)
+      </add>
     </changelog>
   </subsection>
   <subsection name="Other">



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to