You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by va...@apache.org on 2023/05/24 06:30:03 UTC

[qpid-broker-j] branch main updated: QPID-8624: [Broker-J] Unable to auto generate self signed certificate on Java17 (#181)

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

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


The following commit(s) were added to refs/heads/main by this push:
     new ad7b4189df QPID-8624: [Broker-J] Unable to auto generate self signed certificate  on Java17 (#181)
ad7b4189df is described below

commit ad7b4189dfc6b05c3eb599c0731c7a01e28ea607
Author: Daniil Kirilyuk <da...@gmail.com>
AuthorDate: Wed May 24 08:29:57 2023 +0200

    QPID-8624: [Broker-J] Unable to auto generate self signed certificate  on Java17 (#181)
---
 .../dependency-verification/DEPENDENCIES_REFERENCE |   6 +
 broker-core/pom.xml                                |  10 +
 .../AutoGeneratedSelfSignedKeyStoreImpl.java       | 159 +++---
 .../transport/network/security/ssl/SSLUtil.java    | 581 ++++++++-------------
 .../network/security/ssl/SSLUtilTest.java          |  41 ++
 .../engine/retriever/CertificateRetriever.java     |   2 +-
 qpid-test-utils/pom.xml                            |   6 +
 7 files changed, 356 insertions(+), 449 deletions(-)

diff --git a/apache-qpid-broker-j/src/main/assembly/dependency-verification/DEPENDENCIES_REFERENCE b/apache-qpid-broker-j/src/main/assembly/dependency-verification/DEPENDENCIES_REFERENCE
index 10bd48ce8e..dc517ced5c 100644
--- a/apache-qpid-broker-j/src/main/assembly/dependency-verification/DEPENDENCIES_REFERENCE
+++ b/apache-qpid-broker-j/src/main/assembly/dependency-verification/DEPENDENCIES_REFERENCE
@@ -41,6 +41,12 @@ From: 'an unknown organization'
     License: The Apache Software License, Version 2.0  (http://www.apache.org/licenses/LICENSE-2.0.txt)
   - Prometheus Java Span Context Supplier - OpenTelemetry Agent (http://github.com/prometheus/client_java/simpleclient_tracer/simpleclient_tracer_otel_agent) io.prometheus:simpleclient_tracer_otel_agent:bundle:0.16.0
     License: The Apache Software License, Version 2.0  (http://www.apache.org/licenses/LICENSE-2.0.txt)
+  - Bouncy Castle PKIX, CMS, EAC, TSP, PKCS, OCSP, CMP, and CRMF APIs (https://www.bouncycastle.org/java.html) org.bouncycastle:bcpkix-jdk18on:jar:1.72
+    License: Bouncy Castle Licence  (https://www.bouncycastle.org/licence.html)
+  - Bouncy Castle Provider (https://www.bouncycastle.org/java.html) org.bouncycastle:bcprov-jdk18on:jar:1.72
+    License: Bouncy Castle Licence  (https://www.bouncycastle.org/licence.html)
+  - Bouncy Castle ASN.1 Extension and Utility APIs (https://www.bouncycastle.org/java.html) org.bouncycastle:bcutil-jdk18on:jar:1.72
+    License: Bouncy Castle Licence  (https://www.bouncycastle.org/licence.html)
   - dgrid (https://www.webjars.org) org.webjars.bower:dgrid:jar:1.3.3
     License: BSD 3-Clause  (https://spdx.org/licenses/BSD 3-Clause#licenseText)
   - dstore (http://webjars.org) org.webjars.bower:dstore:jar:1.1.2
diff --git a/broker-core/pom.xml b/broker-core/pom.xml
index 873405b3ec..d47c9c3a20 100644
--- a/broker-core/pom.xml
+++ b/broker-core/pom.xml
@@ -60,6 +60,16 @@
       <artifactId>guava</artifactId>
     </dependency>
 
+    <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bcprov-jdk18on</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bcpkix-jdk18on</artifactId>
+    </dependency>
+
      <!-- test dependencies -->
     <dependency>
       <groupId>org.apache.qpid</groupId>
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/AutoGeneratedSelfSignedKeyStoreImpl.java b/broker-core/src/main/java/org/apache/qpid/server/security/AutoGeneratedSelfSignedKeyStoreImpl.java
index 41a9c48cb4..1790b0e6fa 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/AutoGeneratedSelfSignedKeyStoreImpl.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/AutoGeneratedSelfSignedKeyStoreImpl.java
@@ -25,10 +25,10 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.Writer;
-import java.lang.reflect.InvocationTargetException;
 import java.net.InetAddress;
 import java.net.InterfaceAddress;
 import java.net.NetworkInterface;
+import java.net.SocketException;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.security.GeneralSecurityException;
@@ -42,24 +42,29 @@ import java.security.cert.CertificateEncodingException;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
 import java.security.spec.InvalidKeySpecException;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
 import java.util.Arrays;
 import java.util.Base64;
-import java.util.Calendar;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
-import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.KeyManagerFactory;
 
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+import org.bouncycastle.cert.CertIOException;
+import org.bouncycastle.operator.OperatorCreationException;
 
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
-import org.apache.qpid.server.logging.EventLogger;
 import org.apache.qpid.server.model.Broker;
 import org.apache.qpid.server.model.Content;
 import org.apache.qpid.server.model.CustomRestHeaders;
@@ -75,12 +80,8 @@ public class AutoGeneratedSelfSignedKeyStoreImpl
         extends AbstractKeyStore<AutoGeneratedSelfSignedKeyStoreImpl>
         implements AutoGeneratedSelfSignedKeyStore<AutoGeneratedSelfSignedKeyStoreImpl>
 {
-
     private static final SecureRandom RANDOM = new SecureRandom();
 
-    private final Broker<?> _broker;
-    private final EventLogger _eventLogger;
-
     @ManagedAttributeField
     private volatile String _keyAlgorithm;
     @ManagedAttributeField
@@ -97,19 +98,16 @@ public class AutoGeneratedSelfSignedKeyStoreImpl
     private volatile boolean _generated;
     private volatile boolean _created;
 
-
     @ManagedObjectFactoryConstructor(conditionallyAvailable = true)
     public AutoGeneratedSelfSignedKeyStoreImpl(final Map<String, Object> attributes, Broker<?> broker)
     {
         super(attributes, broker);
-        _broker = broker;
-        _eventLogger = _broker.getEventLogger();
     }
 
     @Override
     public KeyManager[] getKeyManagers() throws GeneralSecurityException
     {
-        KeyManager[] keyManagers = _keyManagers;
+        final KeyManager[] keyManagers = _keyManagers;
         return keyManagers == null ? new KeyManager[0] : Arrays.copyOf(keyManagers, keyManagers.length);
     }
 
@@ -160,7 +158,8 @@ public class AutoGeneratedSelfSignedKeyStoreImpl
     protected void postResolve()
     {
         super.postResolve();
-        if(getActualAttributes().containsKey(ENCODED_PRIVATE_KEY) && getActualAttributes().containsKey(ENCODED_CERTIFICATE))
+        if (getActualAttributes().containsKey(ENCODED_PRIVATE_KEY) &&
+            getActualAttributes().containsKey(ENCODED_CERTIFICATE))
         {
             loadPrivateKeyAndCertificate();
         }
@@ -169,17 +168,15 @@ public class AutoGeneratedSelfSignedKeyStoreImpl
             generatePrivateKeyAndCertificate();
         }
         generateKeyManagers();
-
     }
 
     private void loadPrivateKeyAndCertificate()
     {
-        byte[] privateKeyEncoded = Strings.decodeBase64((String) getActualAttributes().get(ENCODED_PRIVATE_KEY));
-        byte[] certificateEncoded = Strings.decodeBase64((String) getActualAttributes().get(
-                ENCODED_CERTIFICATE));
+        final byte[] privateKeyEncoded = Strings.decodeBase64((String) getActualAttributes().get(ENCODED_PRIVATE_KEY));
+        final byte[] certificateEncoded = Strings.decodeBase64((String) getActualAttributes()
+                .get(ENCODED_CERTIFICATE));
 
-
-        try(ByteArrayInputStream input = new ByteArrayInputStream(certificateEncoded))
+        try (final ByteArrayInputStream input = new ByteArrayInputStream(certificateEncoded))
         {
             _certificate = (X509Certificate) SSLUtil.getCertificateFactory().generateCertificate(input);
         }
@@ -215,7 +212,7 @@ public class AutoGeneratedSelfSignedKeyStoreImpl
     @StateTransition(currentState = { State.UNINITIALIZED, State.STOPPED, State.ERRORED}, desiredState = State.ACTIVE)
     protected ListenableFuture<Void> activate()
     {
-        if(!_created)
+        if (!_created)
         {
             saveDerivedAttributesIfNecessary();
         }
@@ -226,7 +223,7 @@ public class AutoGeneratedSelfSignedKeyStoreImpl
 
     private void saveDerivedAttributesIfNecessary()
     {
-        if(_generated)
+        if (_generated)
         {
 
             final Object encodedCertificate = getEncodedCertificate();
@@ -243,71 +240,50 @@ public class AutoGeneratedSelfSignedKeyStoreImpl
     {
         try
         {
+            final Set<InetAddress> addresses = Collections.list(NetworkInterface.getNetworkInterfaces()).stream()
+                    .flatMap(networkInterface -> networkInterface.getInterfaceAddresses().stream())
+                    .map(InterfaceAddress::getAddress)
+                    .collect(Collectors.toSet());
 
+            final Set<String> dnsNames = addresses.stream()
+                    .map(address -> address.getHostName() != null ? address.getHostName() : address.getCanonicalHostName())
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.toSet());
 
-            Set<InetAddress> addresses = new HashSet<>();
-            for (NetworkInterface networkInterface : Collections.list(NetworkInterface.getNetworkInterfaces()))
-            {
-                for (InterfaceAddress inetAddress : networkInterface.getInterfaceAddresses())
-                {
-                    addresses.add(inetAddress.getAddress());
-                }
-            }
+            final long startTime = Instant.now().toEpochMilli();
+            final long endTime = LocalDateTime.now().plusMonths(_durationInMonths).toInstant(ZoneOffset.UTC)
+                    .toEpochMilli();
 
-            Set<String> dnsNames = new HashSet<>();
-
-            for(InetAddress address : addresses)
-            {
-
-                String hostName = address.getHostName();
-                if (hostName != null)
-                {
-                    dnsNames.add(hostName);
-                }
-                String canonicalHostName = address.getCanonicalHostName();
-                if (canonicalHostName != null)
-                {
-                    dnsNames.add(canonicalHostName);
-                }
-            }
-
-            long startTime = System.currentTimeMillis();
-            Calendar calendar = Calendar.getInstance();
-            calendar.setTimeInMillis(startTime);
-            calendar.add(Calendar.MONTH, _durationInMonths);
-            long duration = (calendar.getTimeInMillis() - startTime)/1000;
-
-            final SSLUtil.KeyCertPair keyCertPair = SSLUtil.generateSelfSignedCertificate(_keyAlgorithm,
-                                                                                          _signatureAlgorithm,
-                                                                                          _keyLength,
-                                                                                          startTime,
-                                                                                          duration,
-                                                                                          "CN=Qpid",
-                                                                                          dnsNames,
-                                                                                          addresses);
+            final SSLUtil.KeyCertPair keyCertPair =  SSLUtil.generateSelfSignedCertificate(_keyAlgorithm,
+                    _signatureAlgorithm, _keyLength, startTime, endTime, "CN=Qpid", dnsNames, addresses);
 
             _privateKey = keyCertPair.getPrivateKey();
             _certificate = keyCertPair.getCertificate();
             _generated = true;
 
         }
-        catch (InstantiationException | IllegalAccessException | InvocationTargetException | IOException e)
+        catch (SocketException | NoSuchAlgorithmException | OperatorCreationException | CertificateException |
+               CertIOException e)
         {
             throw new IllegalConfigurationException("Unable to construct keystore", e);
         }
     }
 
+    @Override
+    public List<CertificateDetails> getCertificateDetails()
+    {
+        return List.of(new CertificateDetailsImpl(_certificate, getName()));
+    }
+
     @Override
     protected void checkCertificateExpiry()
     {
-        int expiryWarning = getCertificateExpiryWarnPeriod();
-        if(expiryWarning > 0)
+        final int expiryWarning = getCertificateExpiryWarnPeriod();
+        if (expiryWarning > 0)
         {
-            long currentTime = System.currentTimeMillis();
-            Date expiryTestDate = new Date(currentTime + (ONE_DAY * (long) expiryWarning));
-
-            checkCertificatesExpiry(currentTime, expiryTestDate,
-                                    new X509Certificate[]{_certificate});
+            final long currentTime = System.currentTimeMillis();
+            final Date expiryTestDate = new Date(currentTime + (ONE_DAY * (long) expiryWarning));
+            checkCertificatesExpiry(currentTime, expiryTestDate, new X509Certificate[]{_certificate});
         }
     }
 
@@ -317,24 +293,23 @@ public class AutoGeneratedSelfSignedKeyStoreImpl
         return Collections.singleton(_certificate);
     }
 
-
     private void generateKeyManagers()
     {
         try
         {
-            X509Certificate[] certs = new X509Certificate[] { _certificate };
-
+            final X509Certificate[] certs = new X509Certificate[] { _certificate };
 
-            java.security.KeyStore inMemoryKeyStore = java.security.KeyStore.getInstance(java.security.KeyStore.getDefaultType());
+            final java.security.KeyStore inMemoryKeyStore =
+                    java.security.KeyStore.getInstance(java.security.KeyStore.getDefaultType());
 
-            byte[] bytes = new byte[64];
-            char[] chars = "".toCharArray();
+            final byte[] bytes = new byte[64];
+            final char[] chars = "".toCharArray();
             RANDOM.nextBytes(bytes);
             StandardCharsets.US_ASCII.decode(ByteBuffer.wrap(bytes)).get(chars);
             inMemoryKeyStore.load(null, chars);
             inMemoryKeyStore.setKeyEntry("1", _privateKey, chars, certs);
 
-            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+            final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
             kmf.init(inMemoryKeyStore, chars);
             _keyManagers = kmf.getKeyManagers();
 
@@ -345,8 +320,6 @@ public class AutoGeneratedSelfSignedKeyStoreImpl
         }
     }
 
-
-
     static boolean isAvailable()
     {
         return SSLUtil.canGenerateCerts();
@@ -360,13 +333,11 @@ public class AutoGeneratedSelfSignedKeyStoreImpl
     }
 
     @Override
-    public Content getClientTrustStore(String password)
+    public Content getClientTrustStore(final String password)
     {
-
         try
         {
-            KeyStore inMemoryKeyStore =
-                    KeyStore.getInstance(KeyStore.getDefaultType());
+            final KeyStore inMemoryKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
 
             inMemoryKeyStore.load(null, null);
             inMemoryKeyStore.setCertificateEntry(getName(), _certificate);
@@ -379,7 +350,6 @@ public class AutoGeneratedSelfSignedKeyStoreImpl
         }
     }
 
-
     @Override
     public Content getCertificate()
     {
@@ -391,7 +361,6 @@ public class AutoGeneratedSelfSignedKeyStoreImpl
         {
             throw new IllegalArgumentException("Cannot decode encode the certificate");
         }
-
     }
 
     private static class TrustStoreContent implements Content, CustomRestHeaders
@@ -400,8 +369,7 @@ public class AutoGeneratedSelfSignedKeyStoreImpl
         private final char[] _password;
         private final String _disposition;
 
-        public TrustStoreContent(final KeyStore inMemoryKeyStore,
-                                 final String name, final char[] password)
+        public TrustStoreContent(final KeyStore inMemoryKeyStore, final String name, final char[] password)
         {
             _keyStore = inMemoryKeyStore;
             _password = password;
@@ -432,17 +400,16 @@ public class AutoGeneratedSelfSignedKeyStoreImpl
             return "application/octet-stream";
         }
 
+        @SuppressWarnings("unused")
         @RestContentHeader("Content-Disposition")
         public String getContentDisposition()
         {
             return _disposition;
         }
-
     }
 
     private static class CertificateContent implements Content, CustomRestHeaders
     {
-
         private final String _disposition;
         private final String _certString;
 
@@ -450,12 +417,12 @@ public class AutoGeneratedSelfSignedKeyStoreImpl
                 throws CertificateEncodingException
         {
             _disposition = "attachment; filename=\"" + name + ".pem\"";
-            StringBuilder certStringBuffer = new StringBuilder("-----BEGIN CERTIFICATE-----\n");
-            String cert = Base64.getEncoder().encodeToString(certificate.getEncoded());
+            final StringBuilder certStringBuffer = new StringBuilder("-----BEGIN CERTIFICATE-----\n");
+            final String cert = Base64.getEncoder().encodeToString(certificate.getEncoded());
             int offset = 0;
-            while(cert.length()-offset > 64)
+            while (cert.length() - offset > 64)
             {
-                certStringBuffer.append(cert.substring(offset, offset+64));
+                certStringBuffer.append(cert, offset, offset + 64);
                 offset+=64;
                 certStringBuffer.append("\n");
             }
@@ -467,9 +434,9 @@ public class AutoGeneratedSelfSignedKeyStoreImpl
         @Override
         public void write(final OutputStream outputStream) throws IOException
         {
-            Writer w = new OutputStreamWriter(outputStream);
-            w.write(_certString);
-            w.flush();
+            final Writer writer = new OutputStreamWriter(outputStream);
+            writer.write(_certString);
+            writer.flush();
         }
 
         @Override
@@ -483,13 +450,11 @@ public class AutoGeneratedSelfSignedKeyStoreImpl
             return "text/plain";
         }
 
+        @SuppressWarnings("unused")
         @RestContentHeader("Content-Disposition")
         public String getContentDisposition()
         {
             return _disposition;
         }
-
-
     }
-
 }
diff --git a/broker-core/src/main/java/org/apache/qpid/server/transport/network/security/ssl/SSLUtil.java b/broker-core/src/main/java/org/apache/qpid/server/transport/network/security/ssl/SSLUtil.java
index b11a9e6e46..65a4fc4eeb 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/transport/network/security/ssl/SSLUtil.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/transport/network/security/ssl/SSLUtil.java
@@ -27,9 +27,6 @@ import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.StringReader;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.math.BigInteger;
 import java.net.InetAddress;
 import java.net.URL;
@@ -38,11 +35,16 @@ import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.security.GeneralSecurityException;
 import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
 import java.security.Principal;
 import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.PublicKey;
+import java.security.SecureRandom;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
@@ -63,6 +65,8 @@ import java.util.Map;
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
 
 import javax.naming.InvalidNameException;
 import javax.naming.ldap.LdapName;
@@ -76,9 +80,24 @@ import javax.net.ssl.SSLSocket;
 import javax.net.ssl.StandardConstants;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.X509TrustManager;
+import javax.security.auth.x500.X500Principal;
 
 import org.apache.qpid.server.util.ConnectionScopedRuntimeException;
 import org.apache.qpid.server.util.ServerScopedRuntimeException;
+
+import org.bouncycastle.asn1.x509.BasicConstraints;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.asn1.x509.GeneralName;
+import org.bouncycastle.asn1.x509.GeneralNames;
+import org.bouncycastle.cert.CertIOException;
+import org.bouncycastle.cert.X509v3CertificateBuilder;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
+import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.operator.ContentSigner;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+import org.bouncycastle.util.IPAddress;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -92,108 +111,25 @@ public class SSLUtil
     private static final Logger LOGGER = LoggerFactory.getLogger(SSLUtil.class);
 
     private static final Integer DNS_NAME_TYPE = 2;
-    private static final String[] TLS_PROTOCOL_PREFERENCES = new String[]{"TLSv1.3", "TLSv1.2", "TLSv1.1", "TLS", "TLSv1"};
-
-
-    private static final Constructor<?> CONSTRUCTOR;
-    private static final Method GENERATE_METHOD;
-    private static final Method GET_PRIVATE_KEY_METHOD;
-    private static final Method GET_SELF_CERTIFICATE_METHOD;
-    private static final Constructor<?> X500_NAME_CONSTRUCTOR;
-    private static final Constructor<?> DNS_NAME_CONSTRUCTOR;
-    private static final Constructor<?> IP_ADDR_NAME_CONSTRUCTOR;
-    private static final Constructor<?> GENERAL_NAMES_CONSTRUCTOR;
-    private static final Constructor<?> GENERAL_NAME_CONSTRUCTOR;
-    private static final Method ADD_NAME_TO_NAMES_METHOD;
-    private static final Constructor<?> ALT_NAMES_CONSTRUCTOR;
-    private static final Constructor<?> CERTIFICATE_EXTENSIONS_CONSTRUCTOR;
-    private static final Method SET_EXTENSION_METHOD;
-    private static final Method EXTENSION_GET_NAME_METHOD;
-    private static final boolean CAN_GENERATE_CERTS;
+    private static final String[] TLS_PROTOCOL_PREFERENCES = new String[] { "TLSv1.3", "TLSv1.2", "TLSv1.1", "TLS", "TLSv1" };
+    private static final Pattern DNS_NAME_PATTERN = Pattern.compile("[\\w&&[^\\d]][\\w\\d.-]*");
+
+    private static final Provider PROVIDER = new BouncyCastleProvider();
+    private static final boolean CA_SIGNED = false;
+    private static final boolean CRITICAL = true;
     private static final CertificateFactory CERTIFICATE_FACTORY;
 
     static
     {
-        Constructor<?> constructor = null;
-        Method generateMethod = null;
-        Method getPrivateKeyMethod = null;
-        Method getSelfCertificateMethod = null;
-        Constructor<?> x500NameConstructor = null;
-        Constructor<?> dnsNameConstructor = null;
-        Constructor<?> ipAddrNameConstructor = null;
-        Constructor<?> generalNamesConstructor = null;
-        Constructor<?> generalNameConstructor = null;
-        Method addNameToNamesMethod = null;
-        Constructor<?> altNamesConstructor = null;
-        Constructor<?> certificateExtensionsConstructor = null;
-        Method setExtensionMethod = null;
-        Method extensionGetNameMethod = null;
-        boolean canGenerateCerts = false;
-        CertificateFactory certificateFactory = null;
-
+        CertificateFactory certificateFactory;
         try
         {
             certificateFactory = CertificateFactory.getInstance("X.509");
         }
         catch (CertificateException e)
         {
-            // ignore
+            certificateFactory = null;
         }
-
-        try
-        {
-            Class<?> certAndKeyGenClass;
-            try
-            {
-                certAndKeyGenClass = Class.forName("sun.security.x509.CertAndKeyGen");
-            }
-            catch (ClassNotFoundException e)
-            {
-                certAndKeyGenClass = Class.forName("sun.security.tools.keytool.CertAndKeyGen");
-            }
-
-            final Class<?> x500NameClass = Class.forName("sun.security.x509.X500Name");
-            final Class<?> certificateExtensionsClass = Class.forName("sun.security.x509.CertificateExtensions");
-            final Class<?> generalNamesClass = Class.forName("sun.security.x509.GeneralNames");
-            final Class<?> generalNameClass = Class.forName("sun.security.x509.GeneralName");
-            final Class<?> extensionClass = Class.forName("sun.security.x509.SubjectAlternativeNameExtension");
-
-            constructor = certAndKeyGenClass.getConstructor(String.class, String.class);
-            generateMethod = certAndKeyGenClass.getMethod("generate", Integer.TYPE);
-            getPrivateKeyMethod = certAndKeyGenClass.getMethod("getPrivateKey");
-            getSelfCertificateMethod = certAndKeyGenClass.getMethod("getSelfCertificate", x500NameClass,
-                                                                    Date.class, Long.TYPE, certificateExtensionsClass);
-            x500NameConstructor = x500NameClass.getConstructor(String.class);
-            dnsNameConstructor = Class.forName("sun.security.x509.DNSName").getConstructor(String.class);
-            ipAddrNameConstructor = Class.forName("sun.security.x509.IPAddressName").getConstructor(String.class);
-            generalNamesConstructor = generalNamesClass.getConstructor();
-            generalNameConstructor = generalNameClass.getConstructor(Class.forName("sun.security.x509.GeneralNameInterface"));
-            addNameToNamesMethod = generalNamesClass.getMethod("add", generalNameClass);
-            altNamesConstructor = extensionClass.getConstructor(generalNamesClass);
-            certificateExtensionsConstructor = certificateExtensionsClass.getConstructor();
-            setExtensionMethod = certificateExtensionsClass.getMethod("set", String.class, Object.class);
-            extensionGetNameMethod = extensionClass.getMethod("getName");
-            canGenerateCerts = true;
-        }
-        catch (ClassNotFoundException | LinkageError | NoSuchMethodException e)
-        {
-            // ignore
-        }
-        GET_SELF_CERTIFICATE_METHOD = getSelfCertificateMethod;
-        CONSTRUCTOR = constructor;
-        GENERATE_METHOD = generateMethod;
-        GET_PRIVATE_KEY_METHOD = getPrivateKeyMethod;
-        X500_NAME_CONSTRUCTOR = x500NameConstructor;
-        DNS_NAME_CONSTRUCTOR = dnsNameConstructor;
-        IP_ADDR_NAME_CONSTRUCTOR = ipAddrNameConstructor;
-        GENERAL_NAMES_CONSTRUCTOR = generalNamesConstructor;
-        GENERAL_NAME_CONSTRUCTOR = generalNameConstructor;
-        ADD_NAME_TO_NAMES_METHOD = addNameToNamesMethod;
-        ALT_NAMES_CONSTRUCTOR = altNamesConstructor;
-        CERTIFICATE_EXTENSIONS_CONSTRUCTOR = certificateExtensionsConstructor;
-        SET_EXTENSION_METHOD = setExtensionMethod;
-        EXTENSION_GET_NAME_METHOD = extensionGetNameMethod;
-        CAN_GENERATE_CERTS = canGenerateCerts;
         CERTIFICATE_FACTORY = certificateFactory;
     }
 
@@ -210,11 +146,11 @@ public class SSLUtil
         return CERTIFICATE_FACTORY;
     }
 
-    public static void verifyHostname(SSLEngine engine,String hostnameExpected)
+    public static void verifyHostname(final SSLEngine engine, final String hostnameExpected)
     {
         try
         {
-            Certificate cert = engine.getSession().getPeerCertificates()[0];
+            final Certificate cert = engine.getSession().getPeerCertificates()[0];
             if (cert instanceof X509Certificate)
             {
                 verifyHostname(hostnameExpected, (X509Certificate) cert);
@@ -222,10 +158,10 @@ public class SSLUtil
             else
             {
                 throw new TransportException("Cannot verify peer's hostname as peer does not present a X509Certificate. "
-                                             + "Presented certificate : " + cert);
+                        + "Presented certificate : " + cert);
             }
         }
-        catch(SSLPeerUnverifiedException e)
+        catch (SSLPeerUnverifiedException e)
         {
             throw new TransportException("Failed to verify peer's hostname", e);
         }
@@ -233,29 +169,27 @@ public class SSLUtil
 
     public static void verifyHostname(final String hostnameExpected, final X509Certificate cert)
     {
-
         try
         {
-            SortedSet<String> names = getNamesFromCert(cert);
+            final SortedSet<String> names = getNamesFromCert(cert);
 
             if (names.isEmpty())
             {
                 throw new TransportException("SSL hostname verification failed. Certificate for did not contain CN or DNS subjectAlt");
             }
 
-            boolean match = verifyHostname(hostnameExpected, names);
+            final boolean match = verifyHostname(hostnameExpected, names);
             if (!match)
             {
-                throw new TransportException("SSL hostname verification failed." +
-                                             " Expected : " + hostnameExpected +
-                                             " Found in cert : " + names);
+                throw new TransportException("SSL hostname verification failed. Expected : " +
+                        hostnameExpected + " Found in cert : " + names);
             }
 
         }
         catch (InvalidNameException e)
         {
-            Principal p = cert.getSubjectDN();
-            String dn = p.getName();
+            final Principal p = cert.getSubjectX500Principal();
+            final String dn = p.getName();
             throw new TransportException("SSL hostname verification failed. Could not parse name " + dn, e);
         }
         catch (CertificateParsingException e)
@@ -264,7 +198,7 @@ public class SSLUtil
         }
     }
 
-    public static boolean checkHostname(String hostname, X509Certificate cert)
+    public static boolean checkHostname(final String hostname, final X509Certificate cert)
     {
         try
         {
@@ -281,13 +215,11 @@ public class SSLUtil
         boolean match = false;
 
         final String hostName = hostnameExpected.trim().toLowerCase();
-        for (String cn : names)
+        for (final String cn : names)
         {
-
-            boolean doWildcard = cn.startsWith("*.") &&
-                                 cn.lastIndexOf('.') >= 3 &&
-                                 !cn.matches("\\*\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}");
-
+            final boolean doWildcard = cn.startsWith("*.") &&
+                    cn.lastIndexOf('.') >= 3 &&
+                    !cn.matches("\\*\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}");
 
             match = doWildcard
                     ? hostName.endsWith(cn.substring(1)) && hostName.indexOf(".") == (1 + hostName.length() - cn.length())
@@ -305,11 +237,11 @@ public class SSLUtil
     private static SortedSet<String> getNamesFromCert(final X509Certificate cert)
             throws InvalidNameException, CertificateParsingException
     {
-        Principal p = cert.getSubjectDN();
-        String dn = p.getName();
-        SortedSet<String> names = new TreeSet<>();
-        LdapName ldapName = new LdapName(dn);
-        for (Rdn part : ldapName.getRdns())
+        final Principal p = cert.getSubjectX500Principal();
+        final String dn = p.getName();
+        final SortedSet<String> names = new TreeSet<>();
+        final LdapName ldapName = new LdapName(dn);
+        for (final Rdn part : ldapName.getRdns())
         {
             if (part.getType().equalsIgnoreCase("CN"))
             {
@@ -318,9 +250,9 @@ public class SSLUtil
             }
         }
 
-        if(cert.getSubjectAlternativeNames() != null)
+        if (cert.getSubjectAlternativeNames() != null)
         {
-            for (List<?> entry : cert.getSubjectAlternativeNames())
+            for (final List<?> entry : cert.getSubjectAlternativeNames())
             {
                 if (DNS_NAME_TYPE.equals(entry.get(0)))
                 {
@@ -331,11 +263,11 @@ public class SSLUtil
         return names;
     }
 
-    public static String getIdFromSubjectDN(String dn)
+    public static String getIdFromSubjectDN(final String dn)
     {
         String cnStr = null;
-        String dcStr = null;
-        if(dn == null)
+        StringBuilder dcStr = null;
+        if (dn == null)
         {
             return "";
         }
@@ -343,22 +275,22 @@ public class SSLUtil
         {
             try
             {
-                LdapName ln = new LdapName(dn);
-                for(Rdn rdn : ln.getRdns())
+                final LdapName ln = new LdapName(dn);
+                for (final Rdn rdn : ln.getRdns())
                 {
-                    if("CN".equalsIgnoreCase(rdn.getType()))
+                    if ("CN".equalsIgnoreCase(rdn.getType()))
                     {
                         cnStr = rdn.getValue().toString();
                     }
-                    else if("DC".equalsIgnoreCase(rdn.getType()))
+                    else if ("DC".equalsIgnoreCase(rdn.getType()))
                     {
-                        if(dcStr == null)
+                        if (dcStr == null)
                         {
-                            dcStr = rdn.getValue().toString();
+                            dcStr = new StringBuilder(rdn.getValue().toString());
                         }
                         else
                         {
-                            dcStr = rdn.getValue().toString() + '.' + dcStr;
+                            dcStr.insert(0, rdn.getValue().toString() + '.');
                         }
                     }
                 }
@@ -372,32 +304,16 @@ public class SSLUtil
         }
     }
 
-
-    public static String retrieveIdentity(SSLEngine engine)
-    {
-        String id = "";
-        Certificate cert = engine.getSession().getLocalCertificates()[0];
-        Principal p = ((X509Certificate)cert).getSubjectDN();
-        String dn = p.getName();
-        try
-        {
-            id = SSLUtil.getIdFromSubjectDN(dn);
-        }
-        catch (Exception e)
-        {
-            LOGGER.info("Exception received while trying to retrieve client identity from SSL cert", e);
-        }
-        LOGGER.debug("Extracted Identity from client certificate : {}", id);
-        return id;
-    }
-
-    public static KeyStore getInitializedKeyStore(String storePath, String storePassword, String keyStoreType) throws GeneralSecurityException, IOException
+    public static KeyStore getInitializedKeyStore(final String storePath,
+                                                  final String storePassword,
+                                                  final String keyStoreType)
+            throws GeneralSecurityException, IOException
     {
-        KeyStore ks = KeyStore.getInstance(keyStoreType);
+        final KeyStore ks = KeyStore.getInstance(keyStoreType);
         InputStream in = null;
         try
         {
-            File f = new File(storePath);
+            final File f = new File(storePath);
             if (f.exists())
             {
                 in = new FileInputStream(f);
@@ -411,7 +327,7 @@ public class SSLUtil
                 throw new IOException("Unable to load keystore resource: " + storePath);
             }
 
-            char[] storeCharPassword = storePassword == null ? null : storePassword.toCharArray();
+            final char[] storeCharPassword = storePassword == null ? null : storePassword.toCharArray();
 
             ks.load(in, storeCharPassword);
         }
@@ -432,17 +348,20 @@ public class SSLUtil
         return ks;
     }
 
-    public static KeyStore getInitializedKeyStore(URL storePath, String storePassword, String keyStoreType) throws GeneralSecurityException, IOException
+    public static KeyStore getInitializedKeyStore(final URL storePath,
+                                                  final String storePassword,
+                                                  final String keyStoreType)
+            throws GeneralSecurityException, IOException
     {
-        KeyStore ks = KeyStore.getInstance(keyStoreType);
-        try(InputStream in = storePath.openStream())
+        final KeyStore ks = KeyStore.getInstance(keyStoreType);
+        try (final InputStream in = storePath.openStream())
         {
             if (in == null && !"PKCS11".equalsIgnoreCase(keyStoreType)) // PKCS11 will not require an explicit path
             {
                 throw new IOException("Unable to load keystore resource: " + storePath);
             }
 
-            char[] storeCharPassword = storePassword == null ? null : storePassword.toCharArray();
+            final char[] storeCharPassword = storePassword == null ? null : storePassword.toCharArray();
 
             ks.load(in, storeCharPassword);
         }
@@ -460,67 +379,63 @@ public class SSLUtil
         return ks;
     }
 
-    public static X509Certificate[] readCertificates(URL certFile)
-            throws IOException, GeneralSecurityException
+    public static X509Certificate[] readCertificates(final URL certFile) throws IOException, GeneralSecurityException
     {
-        try (InputStream is = certFile.openStream())
+        try (final InputStream is = certFile.openStream())
         {
             return readCertificates(is);
         }
     }
 
-    public static X509Certificate[] readCertificates(InputStream input)
-            throws IOException, GeneralSecurityException
+    public static X509Certificate[] readCertificates(final InputStream input) throws IOException, GeneralSecurityException
     {
-        List<X509Certificate> crt = new ArrayList<>();
+        final List<X509Certificate> crt = new ArrayList<>();
         try
         {
             do
             {
                 crt.add( (X509Certificate) getCertificateFactory().generateCertificate(input));
-            } while(input.available() != 0);
+            } while (input.available() != 0);
         }
-        catch(CertificateException e)
+        catch (CertificateException e)
         {
-            if(crt.isEmpty())
+            if (crt.isEmpty())
             {
                 throw e;
             }
         }
-        return crt.toArray(new X509Certificate[crt.size()]);
+        return crt.toArray(new X509Certificate[0]);
     }
 
-    public static PrivateKey readPrivateKey(final URL url)
-            throws IOException, GeneralSecurityException
+    public static PrivateKey readPrivateKey(final URL url) throws IOException, GeneralSecurityException
     {
-        try (InputStream urlStream = url.openStream())
+        try (final InputStream urlStream = url.openStream())
         {
             return readPrivateKey(urlStream);
         }
     }
 
-    public static PrivateKey readPrivateKey(InputStream input)
-            throws IOException, GeneralSecurityException
+    public static PrivateKey readPrivateKey(final InputStream input) throws IOException, GeneralSecurityException
     {
         byte[] content = toByteArray(input);
-        String contentAsString = new String(content, StandardCharsets.US_ASCII);
-        if(contentAsString.contains("-----BEGIN ") && contentAsString.contains(" PRIVATE KEY-----"))
+        final String contentAsString = new String(content, StandardCharsets.US_ASCII);
+        if (contentAsString.contains("-----BEGIN ") && contentAsString.contains(" PRIVATE KEY-----"))
         {
-            BufferedReader lineReader = new BufferedReader(new StringReader(contentAsString));
+            final BufferedReader lineReader = new BufferedReader(new StringReader(contentAsString));
 
             String line;
             do
             {
                 line = lineReader.readLine();
-            } while(line != null && !(line.startsWith("-----BEGIN ") && line.endsWith(" PRIVATE KEY-----")));
+            } while (line != null && !(line.startsWith("-----BEGIN ") && line.endsWith(" PRIVATE KEY-----")));
 
-            if(line != null)
+            if (line != null)
             {
-                StringBuilder keyBuilder = new StringBuilder();
+                final StringBuilder keyBuilder = new StringBuilder();
 
-                while((line = lineReader.readLine()) != null)
+                while ((line = lineReader.readLine()) != null)
                 {
-                    if(line.startsWith("-----END ") && line.endsWith(" PRIVATE KEY-----"))
+                    if (line.startsWith("-----END ") && line.endsWith(" PRIVATE KEY-----"))
                     {
                         break;
                     }
@@ -535,17 +450,14 @@ public class SSLUtil
 
     private static byte[] toByteArray(final InputStream input) throws IOException
     {
-        try(ByteArrayOutputStream buffer = new ByteArrayOutputStream())
+        try (final ByteArrayOutputStream buffer = new ByteArrayOutputStream())
         {
-
-            byte[] tmp = new byte[1024];
+            final byte[] tmp = new byte[1024];
             int read;
-            while((read=input.read(tmp))!=-1)
-
+            while ((read = input.read(tmp)) != -1)
             {
                 buffer.write(tmp, 0, read);
             }
-
             return buffer.toByteArray();
         }
     }
@@ -556,31 +468,30 @@ public class SSLUtil
         PrivateKey key;
         try
         {
-            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(content);
-            KeyFactory kf = KeyFactory.getInstance(algorithm);
+            final PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(content);
+            final KeyFactory kf = KeyFactory.getInstance(algorithm);
             key = kf.generatePrivate(keySpec);
         }
-        catch(InvalidKeySpecException e)
+        catch (InvalidKeySpecException e)
         {
             // not in PCKS#8 format - try parsing as PKCS#1
-            RSAPrivateCrtKeySpec keySpec = getRSAKeySpec(content);
-            KeyFactory kf = KeyFactory.getInstance(algorithm);
+            final RSAPrivateCrtKeySpec keySpec = getRSAKeySpec(content);
+            final KeyFactory kf = KeyFactory.getInstance(algorithm);
             try
             {
                 key = kf.generatePrivate(keySpec);
             }
-            catch(InvalidKeySpecException e2)
+            catch (InvalidKeySpecException e2)
             {
                 throw new InvalidKeySpecException("Cannot parse the provided key as either PKCS#1 or PCKS#8 format");
             }
-
         }
         return key;
     }
 
-    private static RSAPrivateCrtKeySpec getRSAKeySpec(byte[] keyBytes) throws InvalidKeySpecException
+    @SuppressWarnings("unused")
+    private static RSAPrivateCrtKeySpec getRSAKeySpec(final byte[] keyBytes) throws InvalidKeySpecException
     {
-
         ByteBuffer buffer = ByteBuffer.wrap(keyBytes);
         try
         {
@@ -588,41 +499,37 @@ public class SSLUtil
             // (version, modulus, publicExponent, privateExponent, primeP, primeQ,
             //  primeExponentP, primeExponentQ, crtCoefficient)
 
-            int tag = ((int)buffer.get()) & 0xff;
+            final int tag = ((int)buffer.get()) & 0xff;
 
             // check tag is that of a sequence
-            if(((tag & 0x20) != 0x20) || ((tag & 0x1F) != 0x10))
+            if (((tag & 0x20) != 0x20) || ((tag & 0x1F) != 0x10))
             {
                 throw new InvalidKeySpecException("Unable to parse key as PKCS#1 format");
             }
 
-            int length = getLength(buffer);
+            final int length = getLength(buffer);
 
             buffer = buffer.slice();
             buffer.limit(length);
 
             // first tlv is version - which we'll ignore
-            byte versionTag = buffer.get();
-            int versionLength = getLength(buffer);
+            final byte versionTag = buffer.get();
+            final int versionLength = getLength(buffer);
             buffer.position(buffer.position()+versionLength);
 
-
-            RSAPrivateCrtKeySpec keySpec = new RSAPrivateCrtKeySpec(
+            return new RSAPrivateCrtKeySpec(
                     getInteger(buffer), getInteger(buffer), getInteger(buffer), getInteger(buffer), getInteger(buffer),
                     getInteger(buffer), getInteger(buffer), getInteger(buffer));
-
-            return keySpec;
         }
-        catch(BufferUnderflowException e)
+        catch (BufferUnderflowException e)
         {
             throw new InvalidKeySpecException("Unable to parse key as PKCS#1 format");
         }
     }
 
-    private static int getLength(ByteBuffer buffer)
+    private static int getLength(final ByteBuffer buffer)
     {
-
-        int i = ((int) buffer.get()) & 0xff;
+        final int i = ((int) buffer.get()) & 0xff;
 
         // length 0 <= i <= 127 encoded as a single byte
         if ((i & ~0x7F) == 0)
@@ -631,21 +538,21 @@ public class SSLUtil
         }
 
         // otherwise the first octet gives us the number of octets needed to read the length
-        byte[] bytes = new byte[i & 0x7f];
+        final byte[] bytes = new byte[i & 0x7f];
         buffer.get(bytes);
 
         return new BigInteger(1, bytes).intValue();
     }
 
-    private static BigInteger getInteger(ByteBuffer buffer) throws InvalidKeySpecException
+    private static BigInteger getInteger(final ByteBuffer buffer) throws InvalidKeySpecException
     {
-        int tag = ((int) buffer.get()) & 0xff;
+        final int tag = ((int) buffer.get()) & 0xff;
         // 0x02 indicates an integer type
         if((tag & 0x1f) != 0x02)
         {
             throw new InvalidKeySpecException("Unable to parse key as PKCS#1 format");
         }
-        byte[] num = new byte[getLength(buffer)];
+        final byte[] num = new byte[getLength(buffer)];
         buffer.get(num);
         return new BigInteger(num);
     }
@@ -654,21 +561,17 @@ public class SSLUtil
                                                  final List<String> protocolAllowList,
                                                  final List<String> protocolDenyList)
     {
-        String[] filteredProtocols = filterEnabledProtocols(engine.getEnabledProtocols(),
-                                                            engine.getSupportedProtocols(),
-                                                            protocolAllowList,
-                                                            protocolDenyList);
+        final String[] filteredProtocols = filterEnabledProtocols(engine.getEnabledProtocols(),
+                engine.getSupportedProtocols(), protocolAllowList, protocolDenyList);
         engine.setEnabledProtocols(filteredProtocols);
     }
 
     public static void updateEnabledTlsProtocols(final SSLSocket socket,
-                                             final List<String> protocolAllowList,
-                                             final List<String> protocolDenyList)
+                                                 final List<String> protocolAllowList,
+                                                 final List<String> protocolDenyList)
     {
-        String[] filteredProtocols = filterEnabledProtocols(socket.getEnabledProtocols(),
-                                                            socket.getSupportedProtocols(),
-                                                            protocolAllowList,
-                                                            protocolDenyList);
+        final String[] filteredProtocols = filterEnabledProtocols(socket.getEnabledProtocols(),
+                socket.getSupportedProtocols(), protocolAllowList, protocolDenyList);
         socket.setEnabledProtocols(filteredProtocols);
     }
 
@@ -688,15 +591,12 @@ public class SSLUtil
         return filterEntries(enabledCipherSuites, supportedCipherSuites, cipherSuiteAllowList, cipherSuiteDenyList);
     }
 
-
     public static void updateEnabledCipherSuites(final SSLEngine engine,
                                                  final List<String> cipherSuitesAllowList,
                                                  final List<String> cipherSuitesDenyList)
     {
-        String[] filteredCipherSuites = filterEntries(engine.getEnabledCipherSuites(),
-                                                      engine.getSupportedCipherSuites(),
-                                                      cipherSuitesAllowList,
-                                                      cipherSuitesDenyList);
+        final String[] filteredCipherSuites = filterEntries(engine.getEnabledCipherSuites(),
+                engine.getSupportedCipherSuites(), cipherSuitesAllowList, cipherSuitesDenyList);
         engine.setEnabledCipherSuites(filteredCipherSuites);
     }
 
@@ -704,10 +604,8 @@ public class SSLUtil
                                                  final List<String> cipherSuitesAllowList,
                                                  final List<String> cipherSuitesDenyList)
     {
-        String[] filteredCipherSuites = filterEntries(socket.getEnabledCipherSuites(),
-                                                      socket.getSupportedCipherSuites(),
-                                                      cipherSuitesAllowList,
-                                                      cipherSuitesDenyList);
+        final String[] filteredCipherSuites = filterEntries(socket.getEnabledCipherSuites(),
+                socket.getSupportedCipherSuites(), cipherSuitesAllowList, cipherSuitesDenyList);
         socket.setEnabledCipherSuites(filteredCipherSuites);
     }
 
@@ -720,14 +618,14 @@ public class SSLUtil
         if (allowList != null && !allowList.isEmpty())
         {
             filteredList = new ArrayList<>();
-            List<String> supportedList = new ArrayList<>(Arrays.asList(supportedEntries));
+            final List<String> supportedList = new ArrayList<>(Arrays.asList(supportedEntries));
             // the outer loop must be over the allow list to preserve its order
-            for (String allowListedRegEx : allowList)
+            for (final String allowListedRegEx : allowList)
             {
-                Iterator<String> supportedIter = supportedList.iterator();
+                final Iterator<String> supportedIter = supportedList.iterator();
                 while (supportedIter.hasNext())
                 {
-                    String supportedEntry = supportedIter.next();
+                    final String supportedEntry = supportedIter.next();
                     if (supportedEntry.matches(allowListedRegEx))
                     {
                         filteredList.add(supportedEntry);
@@ -743,20 +641,13 @@ public class SSLUtil
 
         if (denyList != null && !denyList.isEmpty())
         {
-            for (String denyListedRegEx : denyList)
+            for (final String denyListedRegEx : denyList)
             {
-                Iterator<String> entriesIter = filteredList.iterator();
-                while (entriesIter.hasNext())
-                {
-                    if (entriesIter.next().matches(denyListedRegEx))
-                    {
-                        entriesIter.remove();
-                    }
-                }
+                filteredList.removeIf(s -> s.matches(denyListedRegEx));
             }
         }
 
-        return filteredList.toArray(new String[filteredList.size()]);
+        return filteredList.toArray(new String[0]);
     }
 
     public static SSLContext tryGetSSLContext() throws NoSuchAlgorithmException
@@ -766,7 +657,7 @@ public class SSLUtil
 
     public static SSLContext tryGetSSLContext(final String[] protocols) throws NoSuchAlgorithmException
     {
-        for (String protocol : protocols)
+        for (final String protocol : protocols)
         {
             try
             {
@@ -778,16 +669,16 @@ public class SSLUtil
             }
         }
         throw new NoSuchAlgorithmException(String.format("Could not create SSLContext with one of the requested protocols: %s",
-                                                         Arrays.toString(protocols)));
+                Arrays.toString(protocols)));
     }
 
-    public static boolean isSufficientToDetermineClientSNIHost(QpidByteBuffer buffer)
+    public static boolean isSufficientToDetermineClientSNIHost(final QpidByteBuffer buffer)
     {
-        if(buffer.remaining() < 6)
+        if (buffer.remaining() < 6)
         {
             return false;
         }
-        else if(looksLikeSSLv3ClientHello(buffer))
+        else if (looksLikeSSLv3ClientHello(buffer))
         {
             final int position = buffer.position();
             final int recordSize = 5 + (((buffer.get(position + 3) & 0xFF) << 8) | (buffer.get(position + 4) & 0xFF));
@@ -799,27 +690,27 @@ public class SSLUtil
         }
     }
 
-    private static boolean looksLikeSSLv3ClientHello(QpidByteBuffer buffer)
+    private static boolean looksLikeSSLv3ClientHello(final QpidByteBuffer buffer)
     {
-        int contentType = buffer.get(buffer.position()+0);
-        int majorVersion = buffer.get(buffer.position()+1);
-        int minorVersion = buffer.get(buffer.position()+2);
-        int messageType = buffer.get(buffer.position()+5);
+        final int contentType = buffer.get(buffer.position());
+        final int majorVersion = buffer.get(buffer.position() + 1);
+        final int minorVersion = buffer.get(buffer.position() + 2);
+        final int messageType = buffer.get(buffer.position() + 5);
 
         return contentType == 22 && // SSL Handshake
-                   (majorVersion == 3 && // SSL 3.0 / TLS 1.x
-                    (minorVersion == 0 || // SSL 3.0
-                     minorVersion == 1 || // TLS 1.0
-                     minorVersion == 2 || // TLS 1.1
-                     minorVersion == 3)) && // TLS1.2
-                   (messageType == 1); // client_hello
+                (majorVersion == 3 && // SSL 3.0 / TLS 1.x
+                (minorVersion == 0 || // SSL 3.0
+                minorVersion == 1 || // TLS 1.0
+                minorVersion == 2 || // TLS 1.1
+                minorVersion == 3)) && // TLS1.2
+                (messageType == 1); // client_hello
     }
 
-    public final static String getServerNameFromTLSClientHello(QpidByteBuffer source)
+    @SuppressWarnings("unused")
+    public static String getServerNameFromTLSClientHello(final QpidByteBuffer source)
     {
-        try (QpidByteBuffer input = source.duplicate())
+        try (final QpidByteBuffer input = source.duplicate())
         {
-
             // Do we have a complete header?
             if (!isSufficientToDetermineClientSNIHost(source))
             {
@@ -830,36 +721,34 @@ public class SSLUtil
                 return null;
             }
 
-            byte contentType = input.get();
-            byte majorVersion = input.get();
-            byte minorVersion = input.get();
+            final byte contentType = input.get();
+            final byte majorVersion = input.get();
+            final byte minorVersion = input.get();
             if (minorVersion != 0x00) // not supported for SSL 3.0
             {
-
-                int recordLength = input.getUnsignedShort();
-                int messageType = input.get();
+                final int recordLength = input.getUnsignedShort();
+                final int messageType = input.get();
                 // 24-bit length field
-                int length = (input.getUnsignedByte() << 16) | (input.getUnsignedByte() << 8) | input.getUnsignedByte();
-                if(input.remaining() < length)
+                final int length = (input.getUnsignedByte() << 16) | (input.getUnsignedByte() << 8) | input.getUnsignedByte();
+                if (input.remaining() < length)
                 {
                     return null;
                 }
                 input.limit(length + input.position());
 
                 input.position(input.position() + 34);  // hello minor/major version + random
-                int skip = (int) input.get(); // session-id
+                int skip = input.get(); // session-id
                 input.position(input.position() + skip);
                 skip = input.getUnsignedShort(); // cipher suites
                 input.position(input.position() + skip);
-                skip = (int) input.get(); // compression methods
+                skip = input.get(); // compression methods
                 input.position(input.position() + skip);
 
                 if (input.hasRemaining())
                 {
+                    final int remaining = input.getUnsignedShort();
 
-                    int remaining = input.getUnsignedShort();
-
-                    if(input.remaining() < remaining)
+                    if (input.remaining() < remaining)
                     {
                         // invalid remaining length
                         return null;
@@ -868,17 +757,15 @@ public class SSLUtil
                     input.limit(input.position()+remaining);
                     while (input.hasRemaining())
                     {
-                        int extensionType = input.getUnsignedShort();
-
-                        int extensionLength = input.getUnsignedShort();
+                        final int extensionType = input.getUnsignedShort();
+                        final int extensionLength = input.getUnsignedShort();
 
                         if (extensionType == 0x00)
                         {
-
                             int extensionDataRemaining = extensionLength;
                             if (extensionDataRemaining >= 2)
                             {
-                                int listLength = input.getUnsignedShort();     // length of server_name_list
+                                final int listLength = input.getUnsignedShort();     // length of server_name_list
                                 if (listLength + 2 != extensionDataRemaining)
                                 {
                                     // invalid format
@@ -888,14 +775,14 @@ public class SSLUtil
                                 extensionDataRemaining -= 2;
                                 while (extensionDataRemaining > 0)
                                 {
-                                    int code = input.get();
-                                    int serverNameLength = input.getUnsignedShort();
+                                    final int code = input.get();
+                                    final int serverNameLength = input.getUnsignedShort();
                                     if (serverNameLength > extensionDataRemaining)
                                     {
                                         // invalid format;
                                         return null;
                                     }
-                                    byte[] encoded = new byte[serverNameLength];
+                                    final byte[] encoded = new byte[serverNameLength];
                                     input.get(encoded);
 
                                     if (code == StandardConstants.SNI_HOST_NAME)
@@ -909,7 +796,7 @@ public class SSLUtil
                         }
                         else
                         {
-                            if(input.remaining() < extensionLength)
+                            if (input.remaining() < extensionLength)
                             {
                                 return null;
                             }
@@ -917,12 +804,12 @@ public class SSLUtil
                         }
                     }
                 }
-
             }
             return null;
         }
     }
 
+    @SuppressWarnings("rawtypes")
     public static SSLContext createSslContext(final org.apache.qpid.server.model.KeyStore keyStore,
                                               final Collection<TrustStore> trustStores,
                                               final String portName)
@@ -931,30 +818,30 @@ public class SSLUtil
         try
         {
             sslContext = tryGetSSLContext();
-            KeyManager[] keyManagers = keyStore.getKeyManagers();
+            final KeyManager[] keyManagers = keyStore.getKeyManagers();
 
             TrustManager[] trustManagers;
-            if(trustStores == null || trustStores.isEmpty())
+            if (trustStores == null || trustStores.isEmpty())
             {
                 trustManagers = null;
             }
-            else if(trustStores.size() == 1)
+            else if (trustStores.size() == 1)
             {
                 trustManagers = trustStores.iterator().next().getTrustManagers();
             }
             else
             {
-                Collection<TrustManager> trustManagerList = new ArrayList<>();
+                final Collection<TrustManager> trustManagerList = new ArrayList<>();
                 final QpidMultipleTrustManager mulTrustManager = new QpidMultipleTrustManager();
 
-                for(TrustStore ts : trustStores)
+                for (final TrustStore<?> ts : trustStores)
                 {
-                    TrustManager[] managers = ts.getTrustManagers();
-                    if(managers != null)
+                    final TrustManager[] managers = ts.getTrustManagers();
+                    if (managers != null)
                     {
-                        for(TrustManager manager : managers)
+                        for (final TrustManager manager : managers)
                         {
-                            if(manager instanceof X509TrustManager)
+                            if (manager instanceof X509TrustManager)
                             {
                                 mulTrustManager.addTrustManager((X509TrustManager)manager);
                             }
@@ -965,11 +852,11 @@ public class SSLUtil
                         }
                     }
                 }
-                if(!mulTrustManager.isEmpty())
+                if (!mulTrustManager.isEmpty())
                 {
                     trustManagerList.add(mulTrustManager);
                 }
-                trustManagers = trustManagerList.toArray(new TrustManager[trustManagerList.size()]);
+                trustManagers = trustManagerList.toArray(new TrustManager[0]);
             }
             sslContext.init(keyManagers, trustManagers, null);
         }
@@ -982,75 +869,67 @@ public class SSLUtil
 
     public static boolean canGenerateCerts()
     {
-        return CAN_GENERATE_CERTS;
+        return true;
     }
 
     public static KeyCertPair generateSelfSignedCertificate(final String keyAlgorithm,
                                                             final String signatureAlgorithm,
                                                             final int keyLength,
-                                                            long startTime,
-                                                            long duration,
-                                                            String x500Name,
-                                                            Set<String> dnsNames,
-                                                            Set<InetAddress> addresses)
-            throws IllegalAccessException, InvocationTargetException, InstantiationException
-    {
-        Object certAndKeyGen = CONSTRUCTOR.newInstance(keyAlgorithm, signatureAlgorithm);
-        GENERATE_METHOD.invoke(certAndKeyGen, keyLength);
-        final PrivateKey _privateKey = (PrivateKey) GET_PRIVATE_KEY_METHOD.invoke(certAndKeyGen);
-
-        Object generalNames = GENERAL_NAMES_CONSTRUCTOR.newInstance();
-
-        for(String dnsName : dnsNames)
-        {
-            if(dnsName.matches("[\\w&&[^\\d]][\\w\\d.-]*"))
-            {
-                ADD_NAME_TO_NAMES_METHOD.invoke(generalNames,
-                                                GENERAL_NAME_CONSTRUCTOR.newInstance(DNS_NAME_CONSTRUCTOR.newInstance(
-                                                        dnsName)));
-            }
-        }
-
-        for(InetAddress inetAddress : addresses)
-        {
-            ADD_NAME_TO_NAMES_METHOD.invoke(generalNames, GENERAL_NAME_CONSTRUCTOR.newInstance(IP_ADDR_NAME_CONSTRUCTOR.newInstance(inetAddress.getHostAddress())));
-        }
-        Object certificateExtensions;
-        if(dnsNames.isEmpty() && addresses.isEmpty())
-        {
-            certificateExtensions = null;
-        }
-        else
-        {
-            Object altNamesExtension = ALT_NAMES_CONSTRUCTOR.newInstance(generalNames);
-            certificateExtensions = CERTIFICATE_EXTENSIONS_CONSTRUCTOR.newInstance();
-            SET_EXTENSION_METHOD.invoke(certificateExtensions,
-                                        EXTENSION_GET_NAME_METHOD.invoke(altNamesExtension),
-                                        altNamesExtension);
-        }
-
-        final X509Certificate _certificate = (X509Certificate) GET_SELF_CERTIFICATE_METHOD.invoke(certAndKeyGen,
-                                                                                                  X500_NAME_CONSTRUCTOR
-                                                                                                          .newInstance(x500Name),
-                                                                                                  new Date(startTime),
-                                                                                                  duration,
-                                                                                                  certificateExtensions);
+                                                            final long startTime,
+                                                            final long endTime,
+                                                            final String x500Name,
+                                                            final Set<String> dnsNames,
+                                                            final Set<InetAddress> addresses)
+            throws NoSuchAlgorithmException, OperatorCreationException, CertificateException, CertIOException
+    {
+        final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(keyAlgorithm);
+        keyPairGenerator.initialize(keyLength);
+
+        final KeyPair keyPair = keyPairGenerator.generateKeyPair();
+        final PrivateKey privateKey = keyPair.getPrivate();
+
+        final ContentSigner contentSigner = new JcaContentSignerBuilder(signatureAlgorithm).build(keyPair.getPrivate());
+
+        final GeneralName[] sanLocalHost = Stream.concat(dnsNames.stream()
+                    .filter(dnsName -> DNS_NAME_PATTERN.matcher(dnsName).matches())
+                    .map(dnaName -> new GeneralName(GeneralName.dNSName, dnaName)),
+                addresses.stream()
+                    .map(InetAddress::getHostAddress)
+                    .filter(address -> IPAddress.isValidIPv4(address) || IPAddress.isValidIPv4WithNetmask(address) ||
+                            IPAddress.isValidIPv6(address) || IPAddress.isValidIPv6WithNetmask(address))
+                    .map(address -> new GeneralName(GeneralName.iPAddress, address)))
+                    .toArray(GeneralName[]::new);
+
+        final X500Principal issuerDn = new X500Principal(x500Name);
+        final X500Principal subjectDn = new X500Principal(x500Name);
+        final BigInteger serialNumber = new BigInteger(64, new SecureRandom());
+        final Date startDate = new Date(startTime);
+        final Date endDate = new Date(endTime);
+        final PublicKey publicKey = keyPair.getPublic();
+
+        final X509v3CertificateBuilder certificateBuilder =
+                new JcaX509v3CertificateBuilder(issuerDn, serialNumber, startDate, endDate, subjectDn, publicKey)
+                    .addExtension(Extension.basicConstraints, CRITICAL, new BasicConstraints(CA_SIGNED))
+                    .addExtension(Extension.subjectAlternativeName, false, new GeneralNames(sanLocalHost));
+
+        final X509Certificate certificate = new JcaX509CertificateConverter()
+                .setProvider(PROVIDER)
+                .getCertificate(certificateBuilder.build(contentSigner));
 
         return new KeyCertPair()
         {
             @Override
             public PrivateKey getPrivateKey()
             {
-                return _privateKey;
+                return privateKey;
             }
 
             @Override
             public X509Certificate getCertificate()
             {
-                return _certificate;
+                return certificate;
             }
         };
-
     }
 
     public static Map<String, Certificate> getCertificates(final KeyStore ks) throws KeyStoreException
@@ -1068,7 +947,7 @@ public class SSLUtil
         return certificates;
     }
 
-    public static SNIHostName createSNIHostName(String hostName)
+    public static SNIHostName createSNIHostName(final String hostName)
     {
         try
         {
@@ -1080,7 +959,7 @@ public class SSLUtil
         }
     }
 
-    public static SNIHostName createSNIHostName(byte[] hostName)
+    public static SNIHostName createSNIHostName(final byte[] hostName)
     {
         try
         {
diff --git a/broker-core/src/test/java/org/apache/qpid/server/transport/network/security/ssl/SSLUtilTest.java b/broker-core/src/test/java/org/apache/qpid/server/transport/network/security/ssl/SSLUtilTest.java
index b624635ac4..ebd319fede 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/transport/network/security/ssl/SSLUtilTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/transport/network/security/ssl/SSLUtilTest.java
@@ -24,10 +24,14 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InterfaceAddress;
+import java.net.NetworkInterface;
 import java.net.URL;
 import java.nio.ByteBuffer;
 import java.security.KeyStore;
@@ -36,10 +40,16 @@ import java.security.NoSuchAlgorithmException;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
 import java.util.Arrays;
 import java.util.Base64;
+import java.util.Collections;
 import java.util.Enumeration;
 import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 import javax.net.ssl.KeyManagerFactory;
 import javax.net.ssl.SSLContext;
@@ -226,6 +236,37 @@ public class SSLUtilTest extends UnitTestBase
         assertEquals(certificate, certificates[0], "Unexpected certificate");
     }
 
+    @Test
+    public void generateSelfSignedCertificate() throws Exception
+    {
+        final String keyAlgorithm = "RSA";
+        final String signatureAlgorithm = "SHA256withRSA";
+        final int keyLength = 2048;
+
+        final Set<InetAddress> addresses = Collections.list(NetworkInterface.getNetworkInterfaces()).stream()
+                .flatMap(networkInterface -> networkInterface.getInterfaceAddresses().stream())
+                .map(InterfaceAddress::getAddress)
+                .collect(Collectors.toSet());
+
+        final Set<String> dnsNames = addresses.stream()
+                .map(address -> address.getHostName() != null ? address.getHostName() : address.getCanonicalHostName())
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+
+        final long startTime = System.currentTimeMillis();
+        final long endTime = Instant.ofEpochMilli(startTime).plus(365, ChronoUnit.DAYS).toEpochMilli();
+
+        final SSLUtil.KeyCertPair keyCertPair = SSLUtil.generateSelfSignedCertificate(keyAlgorithm,
+                signatureAlgorithm, keyLength, startTime, endTime, "CN=Qpid", dnsNames, addresses);
+
+        assertNotNull(keyCertPair);
+        assertNotNull(keyCertPair.getCertificate());
+        assertNotNull(keyCertPair.getPrivateKey());
+
+        assertEquals(keyAlgorithm, keyCertPair.getPrivateKey().getAlgorithm());
+        assertTrue(signatureAlgorithm.equalsIgnoreCase(keyCertPair.getCertificate().getSigAlgName()));
+    }
+
     private Certificate getTestCertificate()
             throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException
     {
diff --git a/broker-plugins/query-engine/src/main/java/org/apache/qpid/server/query/engine/retriever/CertificateRetriever.java b/broker-plugins/query-engine/src/main/java/org/apache/qpid/server/query/engine/retriever/CertificateRetriever.java
index a36ea442a4..168bb364ba 100644
--- a/broker-plugins/query-engine/src/main/java/org/apache/qpid/server/query/engine/retriever/CertificateRetriever.java
+++ b/broker-plugins/query-engine/src/main/java/org/apache/qpid/server/query/engine/retriever/CertificateRetriever.java
@@ -78,7 +78,7 @@ public class CertificateRetriever<C extends ConfiguredObject<?>> extends Configu
     private final BiFunction<ConfiguredObject<?>, CertificateDetails, Map<String, Object>> certificateMapping =
         (ConfiguredObject<?> parent, CertificateDetails certificate) -> ImmutableMap.<String, Object>builder()
             .put(_fieldNames.get(0), parent.getName())
-            .put(_fieldNames.get(1), certificate.getAlias())
+            .put(_fieldNames.get(1), certificate.getAlias() == null ? "null" : certificate.getAlias())
             .put(_fieldNames.get(2), certificate.getIssuerName())
             .put(_fieldNames.get(3), certificate.getSerialNumber())
             .put(_fieldNames.get(4), toHex(certificate.getSerialNumber()))
diff --git a/qpid-test-utils/pom.xml b/qpid-test-utils/pom.xml
index 87c26394e9..ff824cd39f 100644
--- a/qpid-test-utils/pom.xml
+++ b/qpid-test-utils/pom.xml
@@ -80,6 +80,12 @@
       <groupId>org.apache.directory.server</groupId>
       <artifactId>apacheds-protocol-ldap</artifactId>
       <scope>compile</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>org.bouncycastle</groupId>
+          <artifactId>bcprov-jdk15on</artifactId>
+        </exclusion>
+      </exclusions>
     </dependency>
     <dependency>
       <groupId>org.apache.directory.server</groupId>


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