You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by or...@apache.org on 2021/02/14 23:02:05 UTC

[qpid-broker-j] 01/04: QPID-8504:[Broker-J]Change encryption mode to GCM

This is an automated email from the ASF dual-hosted git repository.

orudyy pushed a commit to branch 8.0.x
in repository https://gitbox.apache.org/repos/asf/qpid-broker-j.git

commit f0993392c62e85e01f667966a40eca6d9af557db
Author: Dedeepya T <de...@yahoo.co.in>
AuthorDate: Sat Feb 13 13:56:17 2021 +0530

    QPID-8504:[Broker-J]Change encryption mode to GCM
---
 .../encryption/AESGCMKeyFileEncrypter.java         | 115 +++++++
 .../encryption/AESGCMKeyFileEncrypterFactory.java  | 129 ++++++++
 .../security/encryption/AESKeyFileEncrypter.java   |  47 +--
 .../encryption/AESKeyFileEncrypterFactory.java     | 315 ++----------------
 ...ava => AbstractAESKeyFileEncrypterFactory.java} | 234 +++++---------
 .../security/encryption/EncryptionHelper.java      |  72 +++++
 ...java => AESGCMKeyFileEncrypterFactoryTest.java} |  27 +-
 .../encryption/AESGCMKeyFileEncrypterTest.java     | 359 +++++++++++++++++++++
 .../encryption/AESKeyFileEncrypterFactoryTest.java |  20 +-
 .../encryption/AESKeyFileEncrypterTest.java        |  47 ++-
 10 files changed, 835 insertions(+), 530 deletions(-)

diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESGCMKeyFileEncrypter.java b/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESGCMKeyFileEncrypter.java
new file mode 100644
index 0000000..1cf736c
--- /dev/null
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESGCMKeyFileEncrypter.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.security.encryption;
+
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.Base64;
+
+import javax.crypto.Cipher;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.GCMParameterSpec;
+
+import org.apache.qpid.server.util.Strings;
+
+class AESGCMKeyFileEncrypter implements ConfigurationSecretEncrypter
+{
+    private static final String CIPHER_NAME = "AES/GCM/NoPadding";
+    private static final int GCM_INITIALIZATION_VECTOR_LENGTH = 12;
+    private static final int GCM_TAG_LENGTH = 128;
+    private static final String AES_ALGORITHM = "AES";
+    private final SecureRandom _random = new SecureRandom();
+    private final SecretKey _secretKey;
+
+    AESGCMKeyFileEncrypter(SecretKey secretKey)
+    {
+        if (secretKey == null)
+        {
+            throw new IllegalArgumentException("A non null secret key must be supplied");
+        }
+        if (!AES_ALGORITHM.equals(secretKey.getAlgorithm()))
+        {
+            throw new IllegalArgumentException(String.format(
+                    "Provided secret key was for the algorithm: %s when %s was needed.",
+                    secretKey.getAlgorithm(),
+                    AES_ALGORITHM));
+        }
+        _secretKey = secretKey;
+    }
+
+    @Override
+    public String encrypt(final String unencrypted)
+    {
+        byte[] unencryptedBytes = unencrypted.getBytes(StandardCharsets.UTF_8);
+        try
+        {
+            byte[] ivbytes = new byte[GCM_INITIALIZATION_VECTOR_LENGTH];
+            _random.nextBytes(ivbytes);
+            Cipher cipher = Cipher.getInstance(CIPHER_NAME);
+            GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH, ivbytes);
+            cipher.init(Cipher.ENCRYPT_MODE, _secretKey, gcmParameterSpec);
+            byte[] encryptedBytes = EncryptionHelper.readFromCipherStream(unencryptedBytes, cipher);
+            byte[] output = new byte[GCM_INITIALIZATION_VECTOR_LENGTH + encryptedBytes.length];
+            System.arraycopy(ivbytes, 0, output, 0, GCM_INITIALIZATION_VECTOR_LENGTH);
+            System.arraycopy(encryptedBytes, 0, output, GCM_INITIALIZATION_VECTOR_LENGTH, encryptedBytes.length);
+            return Base64.getEncoder().encodeToString(output);
+        }
+        catch (IOException | InvalidAlgorithmParameterException | InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException e)
+        {
+            throw new IllegalArgumentException("Unable to encrypt secret", e);
+        }
+    }
+
+    @Override
+    public String decrypt(final String encrypted)
+    {
+        if (!EncryptionHelper.isValidBase64(encrypted))
+        {
+            throw new IllegalArgumentException("Encrypted value is not valid Base 64 data: '" + encrypted + "'");
+        }
+        byte[] encryptedBytes = Strings.decodeBase64(encrypted);
+        try
+        {
+            Cipher cipher = Cipher.getInstance(CIPHER_NAME);
+            byte[] ivbytes = new byte[GCM_INITIALIZATION_VECTOR_LENGTH];
+            if (encryptedBytes.length >= GCM_INITIALIZATION_VECTOR_LENGTH)
+            {
+                System.arraycopy(encryptedBytes, 0, ivbytes, 0, GCM_INITIALIZATION_VECTOR_LENGTH);
+            }
+            GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH, ivbytes);
+            cipher.init(Cipher.DECRYPT_MODE, _secretKey, gcmParameterSpec);
+            return new String(EncryptionHelper.readFromCipherStream(encryptedBytes,
+                                                                    GCM_INITIALIZATION_VECTOR_LENGTH,
+                                                                    encryptedBytes.length
+                                                                    - GCM_INITIALIZATION_VECTOR_LENGTH,
+                                                                    cipher), StandardCharsets.UTF_8);
+        }
+        catch (IOException | InvalidAlgorithmParameterException | InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException e)
+        {
+            throw new IllegalArgumentException("Unable to decrypt secret", e);
+        }
+    }
+}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESGCMKeyFileEncrypterFactory.java b/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESGCMKeyFileEncrypterFactory.java
new file mode 100644
index 0000000..da6f1ae
--- /dev/null
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESGCMKeyFileEncrypterFactory.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.security.encryption;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import javax.crypto.spec.SecretKeySpec;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.SystemConfig;
+import org.apache.qpid.server.plugin.ConditionallyAvailable;
+import org.apache.qpid.server.plugin.ConfigurationSecretEncrypterFactory;
+import org.apache.qpid.server.plugin.PluggableService;
+
+@PluggableService
+public class AESGCMKeyFileEncrypterFactory extends AbstractAESKeyFileEncrypterFactory
+        implements ConfigurationSecretEncrypterFactory, ConditionallyAvailable
+{
+    public static final String TYPE = "AESGCMKeyFile";
+    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAESKeyFileEncrypterFactory.class);
+
+    @Override
+    public String getType()
+    {
+        return TYPE;
+    }
+
+    @Override
+    public ConfigurationSecretEncrypter createEncrypter(final ConfiguredObject<?> object)
+    {
+        String fileLocation;
+        if (object.getContextKeys(false).contains(ENCRYPTER_KEY_FILE))
+        {
+            fileLocation = object.getContextValue(String.class, ENCRYPTER_KEY_FILE);
+        }
+        else
+        {
+
+            fileLocation = object.getContextValue(String.class, SystemConfig.QPID_WORK_DIR)
+                           + File.separator + DEFAULT_KEYS_SUBDIR_NAME + File.separator
+                           + object.getCategoryClass().getSimpleName() + "_"
+                           + object.getName() + ".key";
+
+            Map<String, String> context = object.getContext();
+            Map<String, String> modifiedContext = new LinkedHashMap<>(context);
+            modifiedContext.put(ENCRYPTER_KEY_FILE, fileLocation);
+
+            object.setAttributes(Collections.<String, Object>singletonMap(ConfiguredObject.CONTEXT, modifiedContext));
+        }
+        File file = new File(fileLocation);
+        if (!file.exists())
+        {
+            LOGGER.warn(
+                    "Configuration encryption is enabled, but no configuration secret was found. A new configuration secret will be created at '{}'.",
+                    fileLocation);
+            try
+            {
+                createAndPopulateKeyFile(file);
+            }
+            catch (IllegalAccessException e)
+            {
+                e.printStackTrace();
+            }
+        }
+        if (!file.isFile())
+        {
+            throw new IllegalArgumentException(String.format("File '%s' is not a regular file.", fileLocation));
+        }
+        try
+        {
+            checkFilePermissions(fileLocation, file);
+            if (Files.size(file.toPath()) != AES_KEY_SIZE_BYTES)
+            {
+                throw new IllegalArgumentException(String.format("Key file '%s' contains an incorrect about of data",
+                                                                 fileLocation));
+            }
+
+            try (FileInputStream inputStream = new FileInputStream(file))
+            {
+                byte[] key = new byte[AES_KEY_SIZE_BYTES];
+                int pos = 0;
+                int read;
+                while (pos < key.length && -1 != (read = inputStream.read(key, pos, key.length - pos)))
+                {
+                    pos += read;
+                }
+                if (pos != key.length)
+                {
+                    throw new IllegalConfigurationException(String.format(
+                            "Key file '%s' contained an incorrect about of data",
+                            fileLocation));
+                }
+                SecretKeySpec keySpec = new SecretKeySpec(key, AES_ALGORITHM);
+                return new AESGCMKeyFileEncrypter(keySpec);
+            }
+        }
+        catch (IOException e)
+        {
+            throw new IllegalConfigurationException("Unable to get file permissions: " + e.getMessage(), e);
+        }
+    }
+}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypter.java b/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypter.java
index ed90d4f..d4a4ace 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypter.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypter.java
@@ -21,7 +21,6 @@
 package org.apache.qpid.server.security.encryption;
 
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.security.InvalidAlgorithmParameterException;
@@ -31,7 +30,6 @@ import java.security.SecureRandom;
 import java.util.Base64;
 
 import javax.crypto.Cipher;
-import javax.crypto.CipherInputStream;
 import javax.crypto.NoSuchPaddingException;
 import javax.crypto.SecretKey;
 import javax.crypto.spec.IvParameterSpec;
@@ -70,7 +68,7 @@ class AESKeyFileEncrypter implements ConfigurationSecretEncrypter
             _random.nextBytes(ivbytes);
             Cipher cipher = Cipher.getInstance(CIPHER_NAME);
             cipher.init(Cipher.ENCRYPT_MODE, _secretKey, new IvParameterSpec(ivbytes));
-            byte[] encryptedBytes = readFromCipherStream(unencryptedBytes, cipher);
+            byte[] encryptedBytes = EncryptionHelper.readFromCipherStream(unencryptedBytes, cipher);
             byte[] output = new byte[AES_INITIALIZATION_VECTOR_LENGTH + encryptedBytes.length];
             System.arraycopy(ivbytes, 0, output, 0, AES_INITIALIZATION_VECTOR_LENGTH);
             System.arraycopy(encryptedBytes, 0, output, AES_INITIALIZATION_VECTOR_LENGTH, encryptedBytes.length);
@@ -85,7 +83,7 @@ class AESKeyFileEncrypter implements ConfigurationSecretEncrypter
     @Override
     public String decrypt(final String encrypted)
     {
-        if(!isValidBase64(encrypted))
+        if(!EncryptionHelper.isValidBase64(encrypted))
         {
             throw new IllegalArgumentException("Encrypted value is not valid Base 64 data: '" + encrypted + "'");
         }
@@ -98,7 +96,7 @@ class AESKeyFileEncrypter implements ConfigurationSecretEncrypter
 
             cipher.init(Cipher.DECRYPT_MODE, _secretKey, ivParameterSpec);
 
-            return new String(readFromCipherStream(encryptedBytes,
+            return new String(EncryptionHelper.readFromCipherStream(encryptedBytes,
                                                    AES_INITIALIZATION_VECTOR_LENGTH,
                                                    encryptedBytes.length - AES_INITIALIZATION_VECTOR_LENGTH,
                                                    cipher), StandardCharsets.UTF_8);
@@ -109,44 +107,5 @@ class AESKeyFileEncrypter implements ConfigurationSecretEncrypter
         }
     }
 
-    private boolean isValidBase64(final String encrypted)
-    {
-        return encrypted.matches("^([\\w\\d+/]{4})*([\\w\\d+/]{2}==|[\\w\\d+/]{3}=)?$");
-    }
-
-
-    private byte[] readFromCipherStream(final byte[] unencryptedBytes, final Cipher cipher) throws IOException
-    {
-        return readFromCipherStream(unencryptedBytes, 0, unencryptedBytes.length, cipher);
-    }
-
-    private byte[] readFromCipherStream(final byte[] unencryptedBytes, int offset, int length, final Cipher cipher)
-            throws IOException
-    {
-        final byte[] encryptedBytes;
-        try (CipherInputStream cipherInputStream = new CipherInputStream(new ByteArrayInputStream(unencryptedBytes,
-                                                                                                  offset,
-                                                                                                  length), cipher))
-        {
-            byte[] buf = new byte[512];
-            int pos = 0;
-            int read;
-            while ((read = cipherInputStream.read(buf, pos, buf.length - pos)) != -1)
-            {
-                pos += read;
-                if (pos == buf.length)
-                {
-                    byte[] tmp = buf;
-                    buf = new byte[buf.length + 512];
-                    System.arraycopy(tmp, 0, buf, 0, tmp.length);
-                }
-            }
-            encryptedBytes = new byte[pos];
-            System.arraycopy(buf, 0, encryptedBytes, 0, pos);
-        }
-        return encryptedBytes;
-    }
-
-
 
 }
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypterFactory.java b/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypterFactory.java
index c176575..cd1797a 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypterFactory.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypterFactory.java
@@ -22,34 +22,12 @@ package org.apache.qpid.server.security.encryption;
 
 import java.io.File;
 import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.attribute.AclEntry;
-import java.nio.file.attribute.AclEntryPermission;
-import java.nio.file.attribute.AclEntryType;
-import java.nio.file.attribute.AclFileAttributeView;
-import java.nio.file.attribute.FileAttribute;
-import java.nio.file.attribute.PosixFileAttributeView;
-import java.nio.file.attribute.PosixFilePermission;
-import java.nio.file.attribute.PosixFilePermissions;
-import java.nio.file.attribute.UserPrincipal;
-import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
-import java.util.EnumSet;
-import java.util.HashSet;
 import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.ListIterator;
 import java.util.Map;
-import java.util.Set;
 
-import javax.crypto.Cipher;
-import javax.crypto.KeyGenerator;
-import javax.crypto.SecretKey;
 import javax.crypto.spec.SecretKeySpec;
 
 import org.slf4j.Logger;
@@ -63,54 +41,23 @@ import org.apache.qpid.server.plugin.ConfigurationSecretEncrypterFactory;
 import org.apache.qpid.server.plugin.PluggableService;
 
 @PluggableService
-public class AESKeyFileEncrypterFactory implements ConfigurationSecretEncrypterFactory, ConditionallyAvailable
+public class AESKeyFileEncrypterFactory extends AbstractAESKeyFileEncrypterFactory
+        implements ConfigurationSecretEncrypterFactory, ConditionallyAvailable
 {
-    private static final Logger LOGGER = LoggerFactory.getLogger(AESKeyFileEncrypterFactory.class);
-
-    static final String ENCRYPTER_KEY_FILE = "encrypter.key.file";
-
-    private static final int AES_KEY_SIZE_BITS = 256;
-    private static final int AES_KEY_SIZE_BYTES = AES_KEY_SIZE_BITS / 8;
-    private static final String AES_ALGORITHM = "AES";
-
     public static final String TYPE = "AESKeyFile";
+    private static final Logger LOGGER = LoggerFactory.getLogger(AESKeyFileEncrypterFactory.class);
 
-    static final String DEFAULT_KEYS_SUBDIR_NAME = ".keys";
-
-    private static final boolean IS_AVAILABLE;
-
-    private static final String ILLEGAL_ARG_EXCEPTION = "Unable to determine a mechanism to protect access to the key file on this filesystem";
-
-    static
+    @Override
+    public String getType()
     {
-        boolean isAvailable;
-        try
-        {
-            final int allowedKeyLength = Cipher.getMaxAllowedKeyLength(AES_ALGORITHM);
-            isAvailable = allowedKeyLength >=AES_KEY_SIZE_BITS;
-            if(!isAvailable)
-            {
-                LOGGER.warn("The {} configuration encryption encryption mechanism is not available. "
-                            + "Maximum available AES key length is {} but {} is required. "
-                            + "Ensure the full strength JCE policy has been installed into your JVM.", TYPE, allowedKeyLength, AES_KEY_SIZE_BITS);
-            }
-        }
-        catch (NoSuchAlgorithmException e)
-        {
-            isAvailable = false;
-
-            LOGGER.error("The " + TYPE + " configuration encryption encryption mechanism is not available. "
-                        + "The " + AES_ALGORITHM + " algorithm is not available within the JVM (despite it being a requirement).");
-        }
-
-        IS_AVAILABLE = isAvailable;
+        return TYPE;
     }
 
     @Override
     public ConfigurationSecretEncrypter createEncrypter(final ConfiguredObject<?> object)
     {
         String fileLocation;
-        if(object.getContextKeys(false).contains(ENCRYPTER_KEY_FILE))
+        if (object.getContextKeys(false).contains(ENCRYPTER_KEY_FILE))
         {
             fileLocation = object.getContextValue(String.class, ENCRYPTER_KEY_FILE);
         }
@@ -129,35 +76,48 @@ public class AESKeyFileEncrypterFactory implements ConfigurationSecretEncrypterF
             object.setAttributes(Collections.<String, Object>singletonMap(ConfiguredObject.CONTEXT, modifiedContext));
         }
         File file = new File(fileLocation);
-        if(!file.exists())
+        if (!file.exists())
         {
-            LOGGER.warn("Configuration encryption is enabled, but no configuration secret was found. A new configuration secret will be created at '{}'.", fileLocation);
-            createAndPopulateKeyFile(file);
+            LOGGER.warn(
+                    "Configuration encryption is enabled, but no configuration secret was found. A new configuration secret will be created at '{}'.",
+                    fileLocation);
+            try
+            {
+                createAndPopulateKeyFile(file);
+            }
+            catch (IllegalAccessException e)
+            {
+                e.printStackTrace();
+            }
         }
-        if(!file.isFile())
+        if (!file.isFile())
         {
-            throw new IllegalArgumentException("File '"+fileLocation+"' is not a regular file.");
+            throw new IllegalArgumentException("File '" + fileLocation + "' is not a regular file.");
         }
         try
         {
             checkFilePermissions(fileLocation, file);
-            if(Files.size(file.toPath()) != AES_KEY_SIZE_BYTES)
+            if (Files.size(file.toPath()) != AES_KEY_SIZE_BYTES)
             {
-                throw new IllegalArgumentException("Key file '" + fileLocation + "' contains an incorrect about of data");
+                throw new IllegalArgumentException("Key file '"
+                                                   + fileLocation
+                                                   + "' contains an incorrect about of data");
             }
 
-            try(FileInputStream inputStream = new FileInputStream(file))
+            try (FileInputStream inputStream = new FileInputStream(file))
             {
                 byte[] key = new byte[AES_KEY_SIZE_BYTES];
                 int pos = 0;
                 int read;
-                while(pos < key.length && -1 != ( read = inputStream.read(key, pos, key.length - pos)))
+                while (pos < key.length && -1 != (read = inputStream.read(key, pos, key.length - pos)))
                 {
                     pos += read;
                 }
-                if(pos != key.length)
+                if (pos != key.length)
                 {
-                    throw new IllegalConfigurationException("Key file '" + fileLocation + "' contained an incorrect about of data");
+                    throw new IllegalConfigurationException(String.format(
+                            "Key file '%s' contained an incorrect about of data",
+                            fileLocation));
                 }
                 SecretKeySpec keySpec = new SecretKeySpec(key, AES_ALGORITHM);
                 return new AESKeyFileEncrypter(keySpec);
@@ -168,217 +128,4 @@ public class AESKeyFileEncrypterFactory implements ConfigurationSecretEncrypterF
             throw new IllegalConfigurationException("Unable to get file permissions: " + e.getMessage(), e);
         }
     }
-
-    private void checkFilePermissions(String fileLocation, File file) throws IOException
-    {
-        if(isPosixFileSystem(file))
-        {
-            Set<PosixFilePermission> permissions = Files.getPosixFilePermissions(file.toPath());
-
-            if (permissions.contains(PosixFilePermission.GROUP_READ)
-                    || permissions.contains(PosixFilePermission.OTHERS_READ)
-                    || permissions.contains(PosixFilePermission.GROUP_WRITE)
-                    || permissions.contains(PosixFilePermission.OTHERS_WRITE)) {
-                throw new IllegalArgumentException("Key file '"
-                        + fileLocation
-                        + "' has incorrect permissions.  Only the owner "
-                        + "should be able to read or write this file.");
-            }
-        }
-        else if(isAclFileSystem(file))
-        {
-            AclFileAttributeView attributeView = Files.getFileAttributeView(file.toPath(), AclFileAttributeView.class);
-            ArrayList<AclEntry> acls = new ArrayList<>(attributeView.getAcl());
-            ListIterator<AclEntry> iter = acls.listIterator();
-            UserPrincipal owner = Files.getOwner(file.toPath());
-            while(iter.hasNext())
-            {
-                AclEntry acl = iter.next();
-                if(acl.type() == AclEntryType.ALLOW)
-                {
-                    Set<AclEntryPermission> originalPermissions = acl.permissions();
-                    Set<AclEntryPermission> updatedPermissions = EnumSet.copyOf(originalPermissions);
-
-
-                    if (updatedPermissions.removeAll(EnumSet.of(AclEntryPermission.APPEND_DATA,
-                            AclEntryPermission.EXECUTE,
-                            AclEntryPermission.WRITE_ACL,
-                            AclEntryPermission.WRITE_DATA,
-                            AclEntryPermission.WRITE_OWNER))) {
-                        throw new IllegalArgumentException("Key file '"
-                                + fileLocation
-                                + "' has incorrect permissions.  The file should not be modifiable by any user.");
-                    }
-                    if (!owner.equals(acl.principal()) && updatedPermissions.removeAll(EnumSet.of(AclEntryPermission.READ_DATA))) {
-                        throw new IllegalArgumentException("Key file '"
-                                + fileLocation
-                                + "' has incorrect permissions.  Only the owner should be able to read from the file.");
-                    }
-                }
-            }
-        }
-        else
-        {
-            throw new IllegalArgumentException(ILLEGAL_ARG_EXCEPTION);
-        }
-    }
-
-    private boolean isPosixFileSystem(File file) throws IOException
-    {
-        return Files.getFileAttributeView(file.toPath(), PosixFileAttributeView.class) != null;
-    }
-
-    private boolean isAclFileSystem(File file) throws IOException
-    {
-        return Files.getFileAttributeView(file.toPath(), AclFileAttributeView.class) != null;
-    }
-
-
-    private void createAndPopulateKeyFile(final File file)
-    {
-        try
-        {
-            createEmptyKeyFile(file);
-
-            KeyGenerator keyGenerator = KeyGenerator.getInstance(AES_ALGORITHM);
-            keyGenerator.init(AES_KEY_SIZE_BITS);
-            SecretKey key = keyGenerator.generateKey();
-            try(FileOutputStream os = new FileOutputStream(file))
-            {
-                os.write(key.getEncoded());
-            }
-
-            makeKeyFileReadOnly(file);
-        }
-        catch (NoSuchAlgorithmException | IOException e)
-        {
-            throw new IllegalArgumentException("Cannot create key file: " + e.getMessage(), e);
-        }
-
-    }
-
-    private void makeKeyFileReadOnly(File file) throws IOException
-    {
-        if(isPosixFileSystem(file))
-        {
-            Files.setPosixFilePermissions(file.toPath(), EnumSet.of(PosixFilePermission.OWNER_READ));
-        }
-        else if(isAclFileSystem(file))
-        {
-            AclFileAttributeView attributeView = Files.getFileAttributeView(file.toPath(), AclFileAttributeView.class);
-            ArrayList<AclEntry> acls = new ArrayList<>(attributeView.getAcl());
-            ListIterator<AclEntry> iter = acls.listIterator();
-            file.setReadOnly();
-            while(iter.hasNext())
-            {
-                AclEntry acl = iter.next();
-                Set<AclEntryPermission> originalPermissions = acl.permissions();
-                Set<AclEntryPermission> updatedPermissions = EnumSet.copyOf(originalPermissions);
-
-                if(updatedPermissions.removeAll(EnumSet.of(AclEntryPermission.APPEND_DATA,
-                                                           AclEntryPermission.DELETE,
-                                                           AclEntryPermission.EXECUTE,
-                                                           AclEntryPermission.WRITE_ACL,
-                                                           AclEntryPermission.WRITE_DATA,
-                                                           AclEntryPermission.WRITE_ATTRIBUTES,
-                                                           AclEntryPermission.WRITE_NAMED_ATTRS,
-                                                           AclEntryPermission.WRITE_OWNER)))
-                {
-                    AclEntry.Builder builder = AclEntry.newBuilder(acl);
-                    builder.setPermissions(updatedPermissions);
-                    iter.set(builder.build());
-                }
-            }
-            attributeView.setAcl(acls);
-        }
-        else
-        {
-            throw new IllegalArgumentException(ILLEGAL_ARG_EXCEPTION);
-        }
-    }
-
-    private void createEmptyKeyFile(File file) throws IOException
-    {
-        final Path parentFilePath = file.getAbsoluteFile().getParentFile().toPath();
-
-        if(isPosixFileSystem(file)) {
-            Set<PosixFilePermission> ownerOnly = EnumSet.of(PosixFilePermission.OWNER_READ,
-                    PosixFilePermission.OWNER_WRITE,
-                    PosixFilePermission.OWNER_EXECUTE);
-            Files.createDirectories(parentFilePath, PosixFilePermissions.asFileAttribute(ownerOnly));
-
-            Files.createFile(file.toPath(), PosixFilePermissions.asFileAttribute(
-                    EnumSet.of(PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE)));
-        }
-        else if(isAclFileSystem(file))
-        {
-            Files.createDirectories(parentFilePath);
-            final UserPrincipal owner = Files.getOwner(parentFilePath);
-            AclFileAttributeView attributeView = Files.getFileAttributeView(parentFilePath, AclFileAttributeView.class);
-            List<AclEntry> acls = new ArrayList<>(attributeView.getAcl());
-            ListIterator<AclEntry> iter = acls.listIterator();
-            boolean found = false;
-            while(iter.hasNext())
-            {
-                AclEntry acl = iter.next();
-                if(!owner.equals(acl.principal()))
-                {
-                    iter.remove();
-                }
-                else if(acl.type() == AclEntryType.ALLOW)
-                {
-                    found = true;
-                    AclEntry.Builder builder = AclEntry.newBuilder(acl);
-                    Set<AclEntryPermission> permissions = acl.permissions().isEmpty() ? new HashSet<AclEntryPermission>() : EnumSet.copyOf(acl.permissions());
-                    permissions.addAll(Arrays.asList(AclEntryPermission.ADD_FILE, AclEntryPermission.ADD_SUBDIRECTORY, AclEntryPermission.LIST_DIRECTORY));
-                    builder.setPermissions(permissions);
-                    iter.set(builder.build());
-                }
-            }
-            if(!found)
-            {
-                AclEntry.Builder builder = AclEntry.newBuilder();
-                builder.setPermissions(AclEntryPermission.ADD_FILE, AclEntryPermission.ADD_SUBDIRECTORY, AclEntryPermission.LIST_DIRECTORY);
-                builder.setType(AclEntryType.ALLOW);
-                builder.setPrincipal(owner);
-                acls.add(builder.build());
-            }
-            attributeView.setAcl(acls);
-
-            Files.createFile(file.toPath(), new FileAttribute<List<AclEntry>>()
-            {
-                @Override
-                public String name()
-                {
-                    return "acl:acl";
-                }
-
-                @Override
-                public List<AclEntry> value() {
-                    AclEntry.Builder builder = AclEntry.newBuilder();
-                    builder.setType(AclEntryType.ALLOW);
-                    builder.setPermissions(EnumSet.allOf(AclEntryPermission.class));
-                    builder.setPrincipal(owner);
-                    return Collections.singletonList(builder.build());
-                }
-            });
-
-        }
-        else
-        {
-            throw new IllegalArgumentException(ILLEGAL_ARG_EXCEPTION);
-        }
-    }
-
-    @Override
-    public String getType()
-    {
-        return TYPE;
-    }
-
-    @Override
-    public boolean isAvailable()
-    {
-        return IS_AVAILABLE;
-    }
 }
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypterFactory.java b/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AbstractAESKeyFileEncrypterFactory.java
similarity index 51%
copy from broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypterFactory.java
copy to broker-core/src/main/java/org/apache/qpid/server/security/encryption/AbstractAESKeyFileEncrypterFactory.java
index c176575..cec40f3 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypterFactory.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AbstractAESKeyFileEncrypterFactory.java
@@ -1,5 +1,4 @@
 /*
- *
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
  * distributed with this work for additional information
@@ -18,10 +17,10 @@
  * under the License.
  *
  */
+
 package org.apache.qpid.server.security.encryption;
 
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.nio.file.Files;
@@ -41,45 +40,38 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashSet;
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.ListIterator;
-import java.util.Map;
 import java.util.Set;
 
 import javax.crypto.Cipher;
 import javax.crypto.KeyGenerator;
 import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
-import org.apache.qpid.server.model.ConfiguredObject;
-import org.apache.qpid.server.model.SystemConfig;
-import org.apache.qpid.server.plugin.ConditionallyAvailable;
-import org.apache.qpid.server.plugin.ConfigurationSecretEncrypterFactory;
-import org.apache.qpid.server.plugin.PluggableService;
-
-@PluggableService
-public class AESKeyFileEncrypterFactory implements ConfigurationSecretEncrypterFactory, ConditionallyAvailable
+
+public abstract class AbstractAESKeyFileEncrypterFactory
 {
-    private static final Logger LOGGER = LoggerFactory.getLogger(AESKeyFileEncrypterFactory.class);
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAESKeyFileEncrypterFactory.class);
 
     static final String ENCRYPTER_KEY_FILE = "encrypter.key.file";
 
     private static final int AES_KEY_SIZE_BITS = 256;
-    private static final int AES_KEY_SIZE_BYTES = AES_KEY_SIZE_BITS / 8;
-    private static final String AES_ALGORITHM = "AES";
+    protected static final int AES_KEY_SIZE_BYTES = AES_KEY_SIZE_BITS / 8;
+    protected static final String AES_ALGORITHM = "AES";
 
-    public static final String TYPE = "AESKeyFile";
+    public static final String TYPE = "AESGCMKeyFile";
 
     static final String DEFAULT_KEYS_SUBDIR_NAME = ".keys";
 
     private static final boolean IS_AVAILABLE;
 
-    private static final String ILLEGAL_ARG_EXCEPTION = "Unable to determine a mechanism to protect access to the key file on this filesystem";
+    private static final String GENERAL_EXCEPTION_MESSAGE =
+            "Unable to determine a mechanism to protect access to the key file on this filesystem";
 
     static
     {
@@ -87,139 +79,74 @@ public class AESKeyFileEncrypterFactory implements ConfigurationSecretEncrypterF
         try
         {
             final int allowedKeyLength = Cipher.getMaxAllowedKeyLength(AES_ALGORITHM);
-            isAvailable = allowedKeyLength >=AES_KEY_SIZE_BITS;
-            if(!isAvailable)
+            isAvailable = allowedKeyLength >= AES_KEY_SIZE_BITS;
+            if (!isAvailable)
             {
                 LOGGER.warn("The {} configuration encryption encryption mechanism is not available. "
                             + "Maximum available AES key length is {} but {} is required. "
-                            + "Ensure the full strength JCE policy has been installed into your JVM.", TYPE, allowedKeyLength, AES_KEY_SIZE_BITS);
+                            + "Ensure the full strength JCE policy has been installed into your JVM.",
+                            TYPE,
+                            allowedKeyLength,
+                            AES_KEY_SIZE_BITS);
             }
         }
         catch (NoSuchAlgorithmException e)
         {
             isAvailable = false;
 
-            LOGGER.error("The " + TYPE + " configuration encryption encryption mechanism is not available. "
-                        + "The " + AES_ALGORITHM + " algorithm is not available within the JVM (despite it being a requirement).");
+            LOGGER.error("The "
+                         + TYPE
+                         + " configuration encryption encryption mechanism is not available. "
+                         + "The "
+                         + AES_ALGORITHM
+                         + " algorithm is not available within the JVM (despite it being a requirement).");
         }
 
         IS_AVAILABLE = isAvailable;
     }
 
-    @Override
-    public ConfigurationSecretEncrypter createEncrypter(final ConfiguredObject<?> object)
-    {
-        String fileLocation;
-        if(object.getContextKeys(false).contains(ENCRYPTER_KEY_FILE))
-        {
-            fileLocation = object.getContextValue(String.class, ENCRYPTER_KEY_FILE);
-        }
-        else
-        {
-
-            fileLocation = object.getContextValue(String.class, SystemConfig.QPID_WORK_DIR)
-                           + File.separator + DEFAULT_KEYS_SUBDIR_NAME + File.separator
-                           + object.getCategoryClass().getSimpleName() + "_"
-                           + object.getName() + ".key";
-
-            Map<String, String> context = object.getContext();
-            Map<String, String> modifiedContext = new LinkedHashMap<>(context);
-            modifiedContext.put(ENCRYPTER_KEY_FILE, fileLocation);
-
-            object.setAttributes(Collections.<String, Object>singletonMap(ConfiguredObject.CONTEXT, modifiedContext));
-        }
-        File file = new File(fileLocation);
-        if(!file.exists())
-        {
-            LOGGER.warn("Configuration encryption is enabled, but no configuration secret was found. A new configuration secret will be created at '{}'.", fileLocation);
-            createAndPopulateKeyFile(file);
-        }
-        if(!file.isFile())
-        {
-            throw new IllegalArgumentException("File '"+fileLocation+"' is not a regular file.");
-        }
-        try
-        {
-            checkFilePermissions(fileLocation, file);
-            if(Files.size(file.toPath()) != AES_KEY_SIZE_BYTES)
-            {
-                throw new IllegalArgumentException("Key file '" + fileLocation + "' contains an incorrect about of data");
-            }
-
-            try(FileInputStream inputStream = new FileInputStream(file))
-            {
-                byte[] key = new byte[AES_KEY_SIZE_BYTES];
-                int pos = 0;
-                int read;
-                while(pos < key.length && -1 != ( read = inputStream.read(key, pos, key.length - pos)))
-                {
-                    pos += read;
-                }
-                if(pos != key.length)
-                {
-                    throw new IllegalConfigurationException("Key file '" + fileLocation + "' contained an incorrect about of data");
-                }
-                SecretKeySpec keySpec = new SecretKeySpec(key, AES_ALGORITHM);
-                return new AESKeyFileEncrypter(keySpec);
-            }
-        }
-        catch (IOException e)
-        {
-            throw new IllegalConfigurationException("Unable to get file permissions: " + e.getMessage(), e);
-        }
-    }
-
-    private void checkFilePermissions(String fileLocation, File file) throws IOException
+    protected void checkFilePermissions(String fileLocation, File file) throws IOException
     {
-        if(isPosixFileSystem(file))
+        if (isPosixFileSystem(file))
         {
             Set<PosixFilePermission> permissions = Files.getPosixFilePermissions(file.toPath());
 
-            if (permissions.contains(PosixFilePermission.GROUP_READ)
-                    || permissions.contains(PosixFilePermission.OTHERS_READ)
-                    || permissions.contains(PosixFilePermission.GROUP_WRITE)
-                    || permissions.contains(PosixFilePermission.OTHERS_WRITE)) {
+            if (permissions.contains(PosixFilePermission.OTHERS_READ)
+                || permissions.contains(PosixFilePermission.OTHERS_WRITE))
+            {
                 throw new IllegalArgumentException("Key file '"
-                        + fileLocation
-                        + "' has incorrect permissions.  Only the owner "
-                        + "should be able to read or write this file.");
+                                                   + fileLocation
+                                                   + "' has incorrect permissions.  Only the owner "
+                                                   + "should be able to read or write this file.");
             }
         }
-        else if(isAclFileSystem(file))
+        else if (isAclFileSystem(file))
         {
             AclFileAttributeView attributeView = Files.getFileAttributeView(file.toPath(), AclFileAttributeView.class);
             ArrayList<AclEntry> acls = new ArrayList<>(attributeView.getAcl());
             ListIterator<AclEntry> iter = acls.listIterator();
             UserPrincipal owner = Files.getOwner(file.toPath());
-            while(iter.hasNext())
+            while (iter.hasNext())
             {
                 AclEntry acl = iter.next();
-                if(acl.type() == AclEntryType.ALLOW)
+                if (acl.type() == AclEntryType.ALLOW)
                 {
                     Set<AclEntryPermission> originalPermissions = acl.permissions();
                     Set<AclEntryPermission> updatedPermissions = EnumSet.copyOf(originalPermissions);
 
-
-                    if (updatedPermissions.removeAll(EnumSet.of(AclEntryPermission.APPEND_DATA,
-                            AclEntryPermission.EXECUTE,
-                            AclEntryPermission.WRITE_ACL,
-                            AclEntryPermission.WRITE_DATA,
-                            AclEntryPermission.WRITE_OWNER))) {
-                        throw new IllegalArgumentException("Key file '"
-                                + fileLocation
-                                + "' has incorrect permissions.  The file should not be modifiable by any user.");
-                    }
-                    if (!owner.equals(acl.principal()) && updatedPermissions.removeAll(EnumSet.of(AclEntryPermission.READ_DATA))) {
-                        throw new IllegalArgumentException("Key file '"
-                                + fileLocation
-                                + "' has incorrect permissions.  Only the owner should be able to read from the file.");
+                    if (!owner.equals(acl.principal())
+                        && updatedPermissions.removeAll(EnumSet.of(AclEntryPermission.READ_DATA)))
+                    {
+                        throw new IllegalArgumentException(String.format(
+                                "Key file '%s' has incorrect permissions.  Only the owner should be able to read from the file.",
+                                fileLocation));
                     }
                 }
             }
         }
         else
         {
-            throw new IllegalArgumentException(ILLEGAL_ARG_EXCEPTION);
+            throw new IllegalArgumentException(GENERAL_EXCEPTION_MESSAGE);
         }
     }
 
@@ -234,7 +161,7 @@ public class AESKeyFileEncrypterFactory implements ConfigurationSecretEncrypterF
     }
 
 
-    private void createAndPopulateKeyFile(final File file)
+    protected void createAndPopulateKeyFile(final File file) throws IllegalAccessException
     {
         try
         {
@@ -243,7 +170,7 @@ public class AESKeyFileEncrypterFactory implements ConfigurationSecretEncrypterF
             KeyGenerator keyGenerator = KeyGenerator.getInstance(AES_ALGORITHM);
             keyGenerator.init(AES_KEY_SIZE_BITS);
             SecretKey key = keyGenerator.generateKey();
-            try(FileOutputStream os = new FileOutputStream(file))
+            try (FileOutputStream os = new FileOutputStream(file))
             {
                 os.write(key.getEncoded());
             }
@@ -252,37 +179,40 @@ public class AESKeyFileEncrypterFactory implements ConfigurationSecretEncrypterF
         }
         catch (NoSuchAlgorithmException | IOException e)
         {
-            throw new IllegalArgumentException("Cannot create key file: " + e.getMessage(), e);
+            throw new IllegalConfigurationException("Cannot create key file: " + e.getMessage(), e);
+        }
+        catch (IllegalAccessException e)
+        {
+            throw new IllegalAccessException("Cannot access key file: " + e);
         }
-
     }
 
-    private void makeKeyFileReadOnly(File file) throws IOException
+    private void makeKeyFileReadOnly(File file) throws IOException, IllegalAccessException
     {
-        if(isPosixFileSystem(file))
+        if (isPosixFileSystem(file))
         {
             Files.setPosixFilePermissions(file.toPath(), EnumSet.of(PosixFilePermission.OWNER_READ));
         }
-        else if(isAclFileSystem(file))
+        else if (isAclFileSystem(file))
         {
             AclFileAttributeView attributeView = Files.getFileAttributeView(file.toPath(), AclFileAttributeView.class);
             ArrayList<AclEntry> acls = new ArrayList<>(attributeView.getAcl());
             ListIterator<AclEntry> iter = acls.listIterator();
             file.setReadOnly();
-            while(iter.hasNext())
+            while (iter.hasNext())
             {
                 AclEntry acl = iter.next();
                 Set<AclEntryPermission> originalPermissions = acl.permissions();
                 Set<AclEntryPermission> updatedPermissions = EnumSet.copyOf(originalPermissions);
 
-                if(updatedPermissions.removeAll(EnumSet.of(AclEntryPermission.APPEND_DATA,
-                                                           AclEntryPermission.DELETE,
-                                                           AclEntryPermission.EXECUTE,
-                                                           AclEntryPermission.WRITE_ACL,
-                                                           AclEntryPermission.WRITE_DATA,
-                                                           AclEntryPermission.WRITE_ATTRIBUTES,
-                                                           AclEntryPermission.WRITE_NAMED_ATTRS,
-                                                           AclEntryPermission.WRITE_OWNER)))
+                if (updatedPermissions.removeAll(EnumSet.of(AclEntryPermission.APPEND_DATA,
+                                                            AclEntryPermission.DELETE,
+                                                            AclEntryPermission.EXECUTE,
+                                                            AclEntryPermission.WRITE_ACL,
+                                                            AclEntryPermission.WRITE_DATA,
+                                                            AclEntryPermission.WRITE_ATTRIBUTES,
+                                                            AclEntryPermission.WRITE_NAMED_ATTRS,
+                                                            AclEntryPermission.WRITE_OWNER)))
                 {
                     AclEntry.Builder builder = AclEntry.newBuilder(acl);
                     builder.setPermissions(updatedPermissions);
@@ -293,7 +223,7 @@ public class AESKeyFileEncrypterFactory implements ConfigurationSecretEncrypterF
         }
         else
         {
-            throw new IllegalArgumentException(ILLEGAL_ARG_EXCEPTION);
+            throw new IllegalAccessException(GENERAL_EXCEPTION_MESSAGE);
         }
     }
 
@@ -301,16 +231,17 @@ public class AESKeyFileEncrypterFactory implements ConfigurationSecretEncrypterF
     {
         final Path parentFilePath = file.getAbsoluteFile().getParentFile().toPath();
 
-        if(isPosixFileSystem(file)) {
+        if (isPosixFileSystem(file))
+        {
             Set<PosixFilePermission> ownerOnly = EnumSet.of(PosixFilePermission.OWNER_READ,
-                    PosixFilePermission.OWNER_WRITE,
-                    PosixFilePermission.OWNER_EXECUTE);
+                                                            PosixFilePermission.OWNER_WRITE,
+                                                            PosixFilePermission.OWNER_EXECUTE);
             Files.createDirectories(parentFilePath, PosixFilePermissions.asFileAttribute(ownerOnly));
 
             Files.createFile(file.toPath(), PosixFilePermissions.asFileAttribute(
                     EnumSet.of(PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE)));
         }
-        else if(isAclFileSystem(file))
+        else if (isAclFileSystem(file))
         {
             Files.createDirectories(parentFilePath);
             final UserPrincipal owner = Files.getOwner(parentFilePath);
@@ -318,27 +249,33 @@ public class AESKeyFileEncrypterFactory implements ConfigurationSecretEncrypterF
             List<AclEntry> acls = new ArrayList<>(attributeView.getAcl());
             ListIterator<AclEntry> iter = acls.listIterator();
             boolean found = false;
-            while(iter.hasNext())
+            while (iter.hasNext())
             {
                 AclEntry acl = iter.next();
-                if(!owner.equals(acl.principal()))
+                if (!owner.equals(acl.principal()))
                 {
                     iter.remove();
                 }
-                else if(acl.type() == AclEntryType.ALLOW)
+                else if (acl.type() == AclEntryType.ALLOW)
                 {
                     found = true;
                     AclEntry.Builder builder = AclEntry.newBuilder(acl);
-                    Set<AclEntryPermission> permissions = acl.permissions().isEmpty() ? new HashSet<AclEntryPermission>() : EnumSet.copyOf(acl.permissions());
-                    permissions.addAll(Arrays.asList(AclEntryPermission.ADD_FILE, AclEntryPermission.ADD_SUBDIRECTORY, AclEntryPermission.LIST_DIRECTORY));
+                    Set<AclEntryPermission> permissions = acl.permissions().isEmpty()
+                            ? new HashSet<AclEntryPermission>()
+                            : EnumSet.copyOf(acl.permissions());
+                    permissions.addAll(Arrays.asList(AclEntryPermission.ADD_FILE,
+                                                     AclEntryPermission.ADD_SUBDIRECTORY,
+                                                     AclEntryPermission.LIST_DIRECTORY));
                     builder.setPermissions(permissions);
                     iter.set(builder.build());
                 }
             }
-            if(!found)
+            if (!found)
             {
                 AclEntry.Builder builder = AclEntry.newBuilder();
-                builder.setPermissions(AclEntryPermission.ADD_FILE, AclEntryPermission.ADD_SUBDIRECTORY, AclEntryPermission.LIST_DIRECTORY);
+                builder.setPermissions(AclEntryPermission.ADD_FILE,
+                                       AclEntryPermission.ADD_SUBDIRECTORY,
+                                       AclEntryPermission.LIST_DIRECTORY);
                 builder.setType(AclEntryType.ALLOW);
                 builder.setPrincipal(owner);
                 acls.add(builder.build());
@@ -354,7 +291,8 @@ public class AESKeyFileEncrypterFactory implements ConfigurationSecretEncrypterF
                 }
 
                 @Override
-                public List<AclEntry> value() {
+                public List<AclEntry> value()
+                {
                     AclEntry.Builder builder = AclEntry.newBuilder();
                     builder.setType(AclEntryType.ALLOW);
                     builder.setPermissions(EnumSet.allOf(AclEntryPermission.class));
@@ -362,23 +300,17 @@ public class AESKeyFileEncrypterFactory implements ConfigurationSecretEncrypterF
                     return Collections.singletonList(builder.build());
                 }
             });
-
         }
         else
         {
-            throw new IllegalArgumentException(ILLEGAL_ARG_EXCEPTION);
+            throw new IllegalArgumentException(GENERAL_EXCEPTION_MESSAGE);
         }
     }
 
-    @Override
-    public String getType()
-    {
-        return TYPE;
-    }
-
-    @Override
     public boolean isAvailable()
     {
         return IS_AVAILABLE;
     }
+
+    public abstract String getType();
 }
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/encryption/EncryptionHelper.java b/broker-core/src/main/java/org/apache/qpid/server/security/encryption/EncryptionHelper.java
new file mode 100644
index 0000000..1f95442
--- /dev/null
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/encryption/EncryptionHelper.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.security.encryption;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import javax.crypto.Cipher;
+import javax.crypto.CipherInputStream;
+
+public class EncryptionHelper
+{
+
+    public static boolean isValidBase64(final String encrypted)
+    {
+        return encrypted.matches("^([\\w\\d+/]{4})*([\\w\\d+/]{2}==|[\\w\\d+/]{3}=)?$");
+    }
+
+
+    public static byte[] readFromCipherStream(final byte[] unencryptedBytes, final Cipher cipher) throws IOException
+    {
+        return readFromCipherStream(unencryptedBytes, 0, unencryptedBytes.length, cipher);
+    }
+
+    public static byte[] readFromCipherStream(final byte[] unencryptedBytes,
+                                              int offset,
+                                              int length,
+                                              final Cipher cipher)
+            throws IOException
+    {
+        final byte[] encryptedBytes;
+        try (CipherInputStream cipherInputStream = new CipherInputStream(new ByteArrayInputStream(unencryptedBytes,
+                                                                                                  offset,
+                                                                                                  length), cipher))
+        {
+            byte[] buf = new byte[512];
+            int pos = 0;
+            int read;
+            while ((read = cipherInputStream.read(buf, pos, buf.length - pos)) != -1)
+            {
+                pos += read;
+                if (pos == buf.length)
+                {
+                    byte[] tmp = buf;
+                    buf = new byte[buf.length + 512];
+                    System.arraycopy(tmp, 0, buf, 0, tmp.length);
+                }
+            }
+            encryptedBytes = new byte[pos];
+            System.arraycopy(buf, 0, encryptedBytes, 0, pos);
+        }
+        return encryptedBytes;
+    }
+}
diff --git a/broker-core/src/test/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypterFactoryTest.java b/broker-core/src/test/java/org/apache/qpid/server/security/encryption/AESGCMKeyFileEncrypterFactoryTest.java
similarity index 95%
copy from broker-core/src/test/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypterFactoryTest.java
copy to broker-core/src/test/java/org/apache/qpid/server/security/encryption/AESGCMKeyFileEncrypterFactoryTest.java
index 9b27904..b30e0c6 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypterFactoryTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/security/encryption/AESGCMKeyFileEncrypterFactoryTest.java
@@ -1,5 +1,4 @@
 /*
- *
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
  * distributed with this work for additional information
@@ -60,11 +59,11 @@ import org.apache.qpid.server.model.Broker;
 import org.apache.qpid.server.model.SystemConfig;
 import org.apache.qpid.test.utils.UnitTestBase;
 
-public class AESKeyFileEncrypterFactoryTest extends UnitTestBase
+public class AESGCMKeyFileEncrypterFactoryTest extends UnitTestBase
 {
     private Broker _broker;
     private Path _tmpDir;
-    private AESKeyFileEncrypterFactory _factory;
+    private AESGCMKeyFileEncrypterFactory _factory;
 
     @Before
     public void setUp() throws Exception
@@ -93,13 +92,13 @@ public class AESKeyFileEncrypterFactoryTest extends UnitTestBase
             }
         }).when(_broker).setAttributes(attributesCaptor.capture());
 
-        _factory = new AESKeyFileEncrypterFactory();
+        _factory = new AESGCMKeyFileEncrypterFactory();
     }
 
     @Test
     public void testCreateKeyInDefaultLocation() throws Exception
     {
-        if(isStrongEncryptionEnabled() && supportsPosixFileAttributes())
+        if (isStrongEncryptionEnabled() && supportsPosixFileAttributes())
         {
             ConfigurationSecretEncrypter encrypter = _factory.createEncrypter(_broker);
 
@@ -132,7 +131,7 @@ public class AESKeyFileEncrypterFactoryTest extends UnitTestBase
     @Test
     public void testSettingContextKeyLeadsToFileCreation() throws Exception
     {
-        if(isStrongEncryptionEnabled() && supportsPosixFileAttributes())
+        if (isStrongEncryptionEnabled() && supportsPosixFileAttributes())
         {
             String filename = UUID.randomUUID().toString() + ".key";
             String subdirName = getTestName() + File.separator + "test";
@@ -154,7 +153,7 @@ public class AESKeyFileEncrypterFactoryTest extends UnitTestBase
     @Test
     public void testUnableToCreateFileInSpecifiedLocation() throws Exception
     {
-        if(isStrongEncryptionEnabled())
+        if (isStrongEncryptionEnabled())
         {
 
             String filename = UUID.randomUUID().toString() + ".key";
@@ -183,7 +182,7 @@ public class AESKeyFileEncrypterFactoryTest extends UnitTestBase
     @Test
     public void testPermissionsAreChecked() throws Exception
     {
-        if(isStrongEncryptionEnabled() && supportsPosixFileAttributes())
+        if (isStrongEncryptionEnabled() && supportsPosixFileAttributes())
         {
 
             String filename = UUID.randomUUID().toString() + ".key";
@@ -216,7 +215,7 @@ public class AESKeyFileEncrypterFactoryTest extends UnitTestBase
     @Test
     public void testInvalidKey() throws Exception
     {
-        if(isStrongEncryptionEnabled() && supportsPosixFileAttributes())
+        if (isStrongEncryptionEnabled() && supportsPosixFileAttributes())
         {
             String filename = UUID.randomUUID().toString() + ".key";
             String subdirName = getTestName() + File.separator + "test";
@@ -279,7 +278,7 @@ public class AESKeyFileEncrypterFactoryTest extends UnitTestBase
 
     private boolean isStrongEncryptionEnabled() throws NoSuchAlgorithmException
     {
-        return Cipher.getMaxAllowedKeyLength("AES")>=256;
+        return Cipher.getMaxAllowedKeyLength("AES") >= 256;
     }
 
     private class KeyFilePathChecker extends SimpleFileVisitor<Path>
@@ -304,7 +303,7 @@ public class AESKeyFileEncrypterFactoryTest extends UnitTestBase
         @Override
         public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) throws IOException
         {
-            if(!_inKeysSubdir && dir.endsWith(_subdirName))
+            if (!_inKeysSubdir && dir.endsWith(_subdirName))
             {
                 _inKeysSubdir = true;
                 assertFalse(Files.getPosixFilePermissions(dir).contains(PosixFilePermission.OTHERS_READ));
@@ -320,15 +319,14 @@ public class AESKeyFileEncrypterFactoryTest extends UnitTestBase
             {
                 return _inKeysSubdir ? FileVisitResult.SKIP_SUBTREE : FileVisitResult.CONTINUE;
             }
-
         }
 
         @Override
         public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException
         {
-            if(_inKeysSubdir)
+            if (_inKeysSubdir)
             {
-                if(file.endsWith(_fileName))
+                if (file.endsWith(_fileName))
                 {
                     _keyFile = file;
 
@@ -357,6 +355,5 @@ public class AESKeyFileEncrypterFactoryTest extends UnitTestBase
         {
             return _keyFile;
         }
-
     }
 }
diff --git a/broker-core/src/test/java/org/apache/qpid/server/security/encryption/AESGCMKeyFileEncrypterTest.java b/broker-core/src/test/java/org/apache/qpid/server/security/encryption/AESGCMKeyFileEncrypterTest.java
new file mode 100644
index 0000000..15bf947
--- /dev/null
+++ b/broker-core/src/test/java/org/apache/qpid/server/security/encryption/AESGCMKeyFileEncrypterTest.java
@@ -0,0 +1,359 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.security.encryption;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.util.concurrent.SettableFuture;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.qpid.server.SystemLauncher;
+import org.apache.qpid.server.SystemLauncherListener;
+import org.apache.qpid.server.model.AuthenticationProvider;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.JsonSystemConfigImpl;
+import org.apache.qpid.server.model.SystemConfig;
+import org.apache.qpid.server.model.User;
+import org.apache.qpid.server.util.FileUtils;
+import org.apache.qpid.test.utils.UnitTestBase;
+
+public class AESGCMKeyFileEncrypterTest extends UnitTestBase
+{
+    private static final String PLAIN_SECRET = "secret";
+    public static final int TIMEOUT = 10;
+    private final SecureRandom _random = new SecureRandom();
+    private static Path _configurationLocation;
+    private static Path _workDir;
+    private Broker<?> _broker;
+    private static SystemLauncher _systemLauncher;
+    private static SecretKeySpec secretKey;
+
+    @Before
+    public void setUp()
+    {
+        final byte[] keyData = new byte[32];
+        _random.nextBytes(keyData);
+        secretKey = new SecretKeySpec(keyData, "AES");
+    }
+
+    private void createBrokerWithEncrypter(final Object encrptionType) throws Exception
+    {
+        _workDir = Files.createTempDirectory("qpid_work_dir");
+        _configurationLocation = Files.createTempFile(_workDir, "config", ".json");
+        Map<String, Object> config = new HashMap<>();
+        config.put(ConfiguredObject.NAME, getTestName());
+        config.put(Broker.MODEL_VERSION, BrokerModel.MODEL_VERSION);
+        config.put(Broker.CONFIDENTIAL_CONFIGURATION_ENCRYPTION_PROVIDER, encrptionType);
+        new ObjectMapper().writeValue(_configurationLocation.toFile(), config);
+
+        Map<String, Object> attributes = new HashMap<>();
+        attributes.put("storePath", _configurationLocation.toFile().getAbsolutePath());
+        attributes.put("preferenceStoreAttributes", "{\"type\": \"Noop\"}");
+        attributes.put(SystemConfig.TYPE, JsonSystemConfigImpl.SYSTEM_CONFIG_TYPE);
+        attributes.put(SystemConfig.STARTUP_LOGGED_TO_SYSTEM_OUT, Boolean.FALSE);
+        attributes.put(SystemConfig.CONTEXT,
+                       Collections.singletonMap("qpid.work_dir", _workDir.toFile().getAbsolutePath()));
+        final SettableFuture<SystemConfig<?>> configFuture = SettableFuture.create();
+        _systemLauncher = new SystemLauncher(new SystemLauncherListener.DefaultSystemLauncherListener()
+        {
+            @Override
+            public void onContainerResolve(final SystemConfig<?> systemConfig)
+            {
+                configFuture.set(systemConfig);
+            }
+        });
+        _systemLauncher.startup(attributes);
+        final SystemConfig<?> systemConfig = configFuture.get(TIMEOUT, TimeUnit.SECONDS);
+        _broker = (Broker<?>) systemConfig.getContainer();
+
+        final Map<String, Object> authProviderAttributes = new HashMap<>();
+        authProviderAttributes.put(ConfiguredObject.NAME, "testAuthProvider");
+        authProviderAttributes.put(ConfiguredObject.TYPE, "Plain");
+
+        final AuthenticationProvider
+                authProvider = _broker.createChild(AuthenticationProvider.class, authProviderAttributes);
+
+        Map<String, Object> userAttrs = new HashMap<>();
+        userAttrs.put(User.TYPE, "managed");
+        userAttrs.put(User.NAME, "guest");
+        userAttrs.put(User.PASSWORD, PLAIN_SECRET);
+        User user = (User) authProvider.createChild(User.class, userAttrs);
+    }
+
+    @AfterClass
+    public static void tearDown() throws Exception
+    {
+        _systemLauncher.shutdown();
+        FileUtils.deleteDirectory(_workDir.toFile().getAbsolutePath());
+        FileUtils.deleteDirectory(_configurationLocation.toFile().getAbsolutePath());
+    }
+
+    @Test
+    public void testRepeatedEncryptionsReturnDifferentValues() throws Exception
+    {
+        AESGCMKeyFileEncrypter encrypter = new AESGCMKeyFileEncrypter(secretKey);
+
+        Set<String> encryptions = new HashSet<>();
+
+        int iterations = 10;
+
+        for (int i = 0; i < iterations; i++)
+        {
+            encryptions.add(encrypter.encrypt(PLAIN_SECRET));
+        }
+
+        assertEquals("Not all encryptions were distinct", (long) iterations, (long) encryptions.size());
+
+        for (String encrypted : encryptions)
+        {
+            assertEquals("Not all encryptions decrypt correctly", PLAIN_SECRET, encrypter.decrypt(encrypted));
+        }
+    }
+
+    @Test
+    public void testCreationFailsOnInvalidSecret() throws Exception
+    {
+        try
+        {
+            new AESGCMKeyFileEncrypter(null);
+            fail("An encrypter should not be creatable from a null key");
+        }
+        catch (IllegalArgumentException e)
+        {
+            assertTrue("Unexpected exception message:" + e.getMessage(),
+                       e.getMessage().contains("A non null secret key must be supplied"));
+        }
+
+        try
+        {
+            PBEKeySpec keySpec = new PBEKeySpec(PLAIN_SECRET.toCharArray());
+            SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
+            new AESGCMKeyFileEncrypter(factory.generateSecret(keySpec));
+            fail("An encrypter should not be creatable from the wrong type of secret key");
+        }
+        catch (IllegalArgumentException e)
+        {
+            assertTrue("Unexpected exception message:" + e.getMessage(),
+                       e.getMessage()
+                        .contains("Provided secret key was for the algorithm: PBEWithMD5AndDES when AES was needed."));
+        }
+    }
+
+    @Test
+    public void testEncryptionOfEmptyString() throws Exception
+    {
+        doTestSimpleEncryptDecrypt("");
+    }
+
+    private void doTestSimpleEncryptDecrypt(final String text)
+    {
+        AESGCMKeyFileEncrypter encrypter = new AESGCMKeyFileEncrypter(secretKey);
+
+        String encrypted = encrypter.encrypt(text);
+        assertNotNull("Encrypter did not return a result from encryption", encrypted);
+        assertNotEquals("Plain text and encrypted version are equal", text, encrypted);
+        String decrypted = encrypter.decrypt(encrypted);
+        assertNotNull("Encrypter did not return a result from decryption", decrypted);
+        assertEquals("Encryption was not reversible", text, decrypted);
+    }
+
+    @Test
+    public void testEncryptingNullFails() throws Exception
+    {
+        try
+        {
+            AESGCMKeyFileEncrypter encrypter = new AESGCMKeyFileEncrypter(secretKey);
+
+            String encrypted = encrypter.encrypt(null);
+            fail("Attempting to encrypt null should fail");
+        }
+        catch (NullPointerException e)
+        {
+            //pass
+        }
+    }
+
+    @Test
+    public void testEncryptingVeryLargeSecret() throws Exception
+    {
+        Random random = new Random();
+        byte[] data = new byte[4096];
+        random.nextBytes(data);
+        for (int i = 0; i < data.length; i++)
+        {
+            data[i] = (byte) (data[i] & 0xEF);
+        }
+        doTestSimpleEncryptDecrypt(new String(data, StandardCharsets.US_ASCII));
+    }
+
+    @Test
+    public void testDecryptNonsense() throws Exception
+    {
+        AESGCMKeyFileEncrypter encrypter = new AESGCMKeyFileEncrypter(secretKey);
+
+        try
+        {
+            encrypter.decrypt(null);
+            fail("Should not decrypt a null value");
+        }
+        catch (NullPointerException e)
+        {
+            // pass
+        }
+
+        try
+        {
+            encrypter.decrypt("");
+            fail("Should not decrypt the empty String");
+        }
+        catch (IllegalArgumentException e)
+        {
+            // pass
+        }
+
+        try
+        {
+            encrypter.decrypt("thisisnonsense");
+            fail("Should not decrypt a small amount of nonsense");
+        }
+        catch (IllegalArgumentException e)
+        {
+            // pass
+        }
+
+        try
+        {
+            String answer = encrypter.decrypt("thisisn'tvalidBase64!soitshouldfailwithanIllegalArgumentException");
+            fail("Should not decrypt a larger amount of nonsense");
+        }
+        catch (IllegalArgumentException e)
+        {
+            // pass
+        }
+    }
+
+    @Test
+    public void testChangeOfEncryptiontoGCM() throws Exception
+    {
+        createBrokerWithEncrypter(AESKeyFileEncrypterFactory.TYPE);
+        String aesEncryptedPassword = getEncryptedPasswordFromConfig();
+        byte[] keyBytes = getSecretKey();
+        final SecretKeySpec aesSecretKey = new SecretKeySpec(keyBytes, "AES");
+        AESKeyFileEncrypter encrypter = new AESKeyFileEncrypter(aesSecretKey);
+        String aesDecryptedPassword = encrypter.decrypt(aesEncryptedPassword);
+        assertEquals("Decrpted text doesnt match original", PLAIN_SECRET, aesDecryptedPassword);
+        _broker.setAttributes(Collections.singletonMap(Broker.CONFIDENTIAL_CONFIGURATION_ENCRYPTION_PROVIDER,
+                                                       AESGCMKeyFileEncrypterFactory.TYPE));
+        String gcmencryptedPassword = getEncryptedPasswordFromConfig();
+        AESGCMKeyFileEncrypter gcmEncrypter = new AESGCMKeyFileEncrypter(aesSecretKey);
+        String gcmDecryptedPassword = gcmEncrypter.decrypt(gcmencryptedPassword);
+        assertEquals("Decrpted text doesnt match original", PLAIN_SECRET, gcmDecryptedPassword);
+    }
+
+    @Test
+    public void testChangeOfEncryptiontoAES() throws Exception
+    {
+        createBrokerWithEncrypter(AESGCMKeyFileEncrypterFactory.TYPE);
+        String gcmEncryptedPassword = getEncryptedPasswordFromConfig();
+        byte[] keyBytes = getSecretKey();
+        final SecretKeySpec aesSecretKey = new SecretKeySpec(keyBytes, "AES");
+        AESGCMKeyFileEncrypter gcmEncrypter = new AESGCMKeyFileEncrypter(aesSecretKey);
+        String gcmDecryptedPassword = gcmEncrypter.decrypt(gcmEncryptedPassword);
+        assertEquals("Decrpted text doesnt match original", PLAIN_SECRET, gcmDecryptedPassword);
+        _broker.setAttributes(Collections.singletonMap(Broker.CONFIDENTIAL_CONFIGURATION_ENCRYPTION_PROVIDER,
+                                                       "AESKeyFile"));
+        String aesencryptedPassword = getEncryptedPasswordFromConfig();
+        AESKeyFileEncrypter aesEncrypter = new AESKeyFileEncrypter(aesSecretKey);
+        String aesDecryptedPassword = aesEncrypter.decrypt(aesencryptedPassword);
+        assertEquals("Decrpted text doesnt match original", PLAIN_SECRET, aesDecryptedPassword);
+    }
+
+    private byte[] getSecretKey() throws IOException
+    {
+        byte[] keyBytes = new byte[0];
+        boolean isSecretFound = false;
+        File[] workDir = _workDir.toFile().listFiles();
+
+        for (File file : workDir)
+        {
+            if (file.isDirectory())
+            {
+                File[] keysDir = file.listFiles();
+                for (File keysFile : keysDir)
+                {
+                    File secretKeyFile = keysFile;
+                    keyBytes = Files.readAllBytes(Paths.get(String.valueOf(secretKeyFile)));
+                    isSecretFound = true;
+                    break;
+                }
+                if (isSecretFound)
+                {
+                    break;
+                }
+            }
+        }
+        return keyBytes;
+    }
+
+    private String getEncryptedPasswordFromConfig() throws java.io.IOException
+    {
+        ObjectMapper objectMapper = new ObjectMapper();
+        File configFile = _configurationLocation.toFile();
+        TypeReference<HashMap<String, Object>> typeRef = new TypeReference<HashMap<String, Object>>()
+        {
+        };
+        HashMap<String, Object> configEntry = objectMapper.readValue(configFile, typeRef);
+        ArrayList configAuthProvider = (ArrayList) configEntry.get("authenticationproviders");
+        HashMap<String, Object> users = (HashMap<String, Object>) configAuthProvider.get(0);
+        ArrayList configUsers = (ArrayList) users.get("users");
+        HashMap<String, Object> configUser = (HashMap<String, Object>) configUsers.get(0);
+        return (String) configUser.get("password");
+    }
+}
diff --git a/broker-core/src/test/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypterFactoryTest.java b/broker-core/src/test/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypterFactoryTest.java
index 9b27904..c7bbbd8 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypterFactoryTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypterFactoryTest.java
@@ -99,7 +99,7 @@ public class AESKeyFileEncrypterFactoryTest extends UnitTestBase
     @Test
     public void testCreateKeyInDefaultLocation() throws Exception
     {
-        if(isStrongEncryptionEnabled() && supportsPosixFileAttributes())
+        if (isStrongEncryptionEnabled() && supportsPosixFileAttributes())
         {
             ConfigurationSecretEncrypter encrypter = _factory.createEncrypter(_broker);
 
@@ -132,7 +132,7 @@ public class AESKeyFileEncrypterFactoryTest extends UnitTestBase
     @Test
     public void testSettingContextKeyLeadsToFileCreation() throws Exception
     {
-        if(isStrongEncryptionEnabled() && supportsPosixFileAttributes())
+        if (isStrongEncryptionEnabled() && supportsPosixFileAttributes())
         {
             String filename = UUID.randomUUID().toString() + ".key";
             String subdirName = getTestName() + File.separator + "test";
@@ -154,7 +154,7 @@ public class AESKeyFileEncrypterFactoryTest extends UnitTestBase
     @Test
     public void testUnableToCreateFileInSpecifiedLocation() throws Exception
     {
-        if(isStrongEncryptionEnabled())
+        if (isStrongEncryptionEnabled())
         {
 
             String filename = UUID.randomUUID().toString() + ".key";
@@ -183,7 +183,7 @@ public class AESKeyFileEncrypterFactoryTest extends UnitTestBase
     @Test
     public void testPermissionsAreChecked() throws Exception
     {
-        if(isStrongEncryptionEnabled() && supportsPosixFileAttributes())
+        if (isStrongEncryptionEnabled() && supportsPosixFileAttributes())
         {
 
             String filename = UUID.randomUUID().toString() + ".key";
@@ -216,7 +216,7 @@ public class AESKeyFileEncrypterFactoryTest extends UnitTestBase
     @Test
     public void testInvalidKey() throws Exception
     {
-        if(isStrongEncryptionEnabled() && supportsPosixFileAttributes())
+        if (isStrongEncryptionEnabled() && supportsPosixFileAttributes())
         {
             String filename = UUID.randomUUID().toString() + ".key";
             String subdirName = getTestName() + File.separator + "test";
@@ -279,7 +279,7 @@ public class AESKeyFileEncrypterFactoryTest extends UnitTestBase
 
     private boolean isStrongEncryptionEnabled() throws NoSuchAlgorithmException
     {
-        return Cipher.getMaxAllowedKeyLength("AES")>=256;
+        return Cipher.getMaxAllowedKeyLength("AES") >= 256;
     }
 
     private class KeyFilePathChecker extends SimpleFileVisitor<Path>
@@ -304,7 +304,7 @@ public class AESKeyFileEncrypterFactoryTest extends UnitTestBase
         @Override
         public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) throws IOException
         {
-            if(!_inKeysSubdir && dir.endsWith(_subdirName))
+            if (!_inKeysSubdir && dir.endsWith(_subdirName))
             {
                 _inKeysSubdir = true;
                 assertFalse(Files.getPosixFilePermissions(dir).contains(PosixFilePermission.OTHERS_READ));
@@ -320,15 +320,14 @@ public class AESKeyFileEncrypterFactoryTest extends UnitTestBase
             {
                 return _inKeysSubdir ? FileVisitResult.SKIP_SUBTREE : FileVisitResult.CONTINUE;
             }
-
         }
 
         @Override
         public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException
         {
-            if(_inKeysSubdir)
+            if (_inKeysSubdir)
             {
-                if(file.endsWith(_fileName))
+                if (file.endsWith(_fileName))
                 {
                     _keyFile = file;
 
@@ -357,6 +356,5 @@ public class AESKeyFileEncrypterFactoryTest extends UnitTestBase
         {
             return _keyFile;
         }
-
     }
 }
diff --git a/broker-core/src/test/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypterTest.java b/broker-core/src/test/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypterTest.java
index 371b683..8f0f8a8 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypterTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypterTest.java
@@ -38,6 +38,7 @@ import javax.crypto.SecretKeyFactory;
 import javax.crypto.spec.PBEKeySpec;
 import javax.crypto.spec.SecretKeySpec;
 
+import org.junit.Before;
 import org.junit.Test;
 
 import org.apache.qpid.test.utils.UnitTestBase;
@@ -45,12 +46,21 @@ import org.apache.qpid.test.utils.UnitTestBase;
 public class AESKeyFileEncrypterTest extends UnitTestBase
 {
     private final SecureRandom _random = new SecureRandom();
-    public static final String PLAINTEXT = "notaverygoodpassword";
+    public static final String PLAINTEXT = "secret";
+    private static SecretKeySpec secretKey;
+
+    @Before
+    public void setUp()
+    {
+        final byte[] keyData = new byte[32];
+        _random.nextBytes(keyData);
+        secretKey = new SecretKeySpec(keyData, "AES");
+    }
 
     @Test
     public void testSimpleEncryptDecrypt() throws Exception
     {
-        if(isStrongEncryptionEnabled())
+        if (isStrongEncryptionEnabled())
         {
             doTestSimpleEncryptDecrypt(PLAINTEXT);
         }
@@ -60,14 +70,13 @@ public class AESKeyFileEncrypterTest extends UnitTestBase
     @Test
     public void testRepeatedEncryptionsReturnDifferentValues() throws Exception
     {
-        if(isStrongEncryptionEnabled())
+        if (isStrongEncryptionEnabled())
         {
-            SecretKeySpec secretKey = createSecretKey();
             AESKeyFileEncrypter encrypter = new AESKeyFileEncrypter(secretKey);
 
             Set<String> encryptions = new HashSet<>();
 
-            int iterations = 100;
+            int iterations = 10;
 
             for (int i = 0; i < iterations; i++)
             {
@@ -86,7 +95,7 @@ public class AESKeyFileEncrypterTest extends UnitTestBase
     @Test
     public void testCreationFailsOnInvalidSecret() throws Exception
     {
-        if(isStrongEncryptionEnabled())
+        if (isStrongEncryptionEnabled())
         {
             try
             {
@@ -115,7 +124,7 @@ public class AESKeyFileEncrypterTest extends UnitTestBase
     @Test
     public void testEncryptionOfEmptyString() throws Exception
     {
-        if(isStrongEncryptionEnabled())
+        if (isStrongEncryptionEnabled())
         {
             String text = "";
             doTestSimpleEncryptDecrypt(text);
@@ -124,7 +133,6 @@ public class AESKeyFileEncrypterTest extends UnitTestBase
 
     private void doTestSimpleEncryptDecrypt(final String text)
     {
-        SecretKeySpec secretKey = createSecretKey();
         AESKeyFileEncrypter encrypter = new AESKeyFileEncrypter(secretKey);
 
         String encrypted = encrypter.encrypt(text);
@@ -138,13 +146,12 @@ public class AESKeyFileEncrypterTest extends UnitTestBase
     @Test
     public void testEncryptingNullFails() throws Exception
     {
-        if(isStrongEncryptionEnabled())
+        if (isStrongEncryptionEnabled())
         {
+            AESKeyFileEncrypter encrypter = new AESKeyFileEncrypter(secretKey);
+
             try
             {
-                SecretKeySpec secretKey = createSecretKey();
-                AESKeyFileEncrypter encrypter = new AESKeyFileEncrypter(secretKey);
-
                 String encrypted = encrypter.encrypt(null);
                 fail("Attempting to encrypt null should fail");
             }
@@ -158,7 +165,7 @@ public class AESKeyFileEncrypterTest extends UnitTestBase
     @Test
     public void testEncryptingVeryLargeSecret() throws Exception
     {
-        if(isStrongEncryptionEnabled())
+        if (isStrongEncryptionEnabled())
         {
             Random random = new Random();
             byte[] data = new byte[4096];
@@ -173,18 +180,15 @@ public class AESKeyFileEncrypterTest extends UnitTestBase
 
     private boolean isStrongEncryptionEnabled() throws NoSuchAlgorithmException
     {
-        return Cipher.getMaxAllowedKeyLength("AES")>=256;
+        return Cipher.getMaxAllowedKeyLength("AES") >= 256;
     }
 
     @Test
     public void testDecryptNonsense() throws Exception
     {
-        if(isStrongEncryptionEnabled())
+        if (isStrongEncryptionEnabled())
         {
-            SecretKeySpec secretKey = createSecretKey();
             AESKeyFileEncrypter encrypter = new AESKeyFileEncrypter(secretKey);
-
-
             try
             {
                 encrypter.decrypt(null);
@@ -226,11 +230,4 @@ public class AESKeyFileEncrypterTest extends UnitTestBase
             }
         }
     }
-
-    private SecretKeySpec createSecretKey()
-    {
-        final byte[] keyData = new byte[32];
-        _random.nextBytes(keyData);
-        return new SecretKeySpec(keyData, "AES");
-    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org