diff --git a/pom.xml b/pom.xml
index f5aad4860ec43..4709238c222e3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1488,6 +1488,8 @@ flexible messaging model and an intuitive client API.
**/*.crt
**/*.key
**/*.csr
+ **/*.srl
+ **/*.txt
**/*.pem
**/*.json
**/*.htpasswd
diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/auth/MockedPulsarServiceBaseTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/auth/MockedPulsarServiceBaseTest.java
index d88a411be34cf..dece46f3ea3f6 100644
--- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/auth/MockedPulsarServiceBaseTest.java
+++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/auth/MockedPulsarServiceBaseTest.java
@@ -25,9 +25,13 @@
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
+
import com.google.common.collect.Sets;
+import com.google.common.io.Resources;
import com.google.common.util.concurrent.MoreExecutors;
import io.netty.channel.EventLoopGroup;
+
+import java.io.File;
import java.lang.reflect.Field;
import java.net.InetSocketAddress;
import java.net.URI;
@@ -43,6 +47,7 @@
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import java.util.function.Supplier;
+
import org.apache.bookkeeper.client.BookKeeper;
import org.apache.bookkeeper.client.EnsemblePlacementPolicy;
import org.apache.bookkeeper.client.PulsarMockBookKeeper;
@@ -79,6 +84,7 @@
import org.awaitility.reflect.WhiteboxImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper;
import org.testng.annotations.DataProvider;
/**
@@ -94,7 +100,7 @@ public abstract class MockedPulsarServiceBaseTest extends TestRetrySupport {
protected PulsarAdmin admin;
protected PulsarClient pulsarClient;
protected PortForwarder brokerGateway;
- protected boolean enableBrokerGateway = false;
+ protected boolean enableBrokerGateway = false;
protected URL brokerUrl;
protected URL brokerUrlTls;
@@ -235,7 +241,7 @@ protected final void internalCleanup() throws Exception {
mockZooKeeper.shutdown();
mockZooKeeper = null;
}
- if(sameThreadOrderedSafeExecutor != null) {
+ if (sameThreadOrderedSafeExecutor != null) {
try {
sameThreadOrderedSafeExecutor.shutdownNow();
sameThreadOrderedSafeExecutor.awaitTermination(5, TimeUnit.SECONDS);
@@ -245,7 +251,7 @@ protected final void internalCleanup() throws Exception {
}
sameThreadOrderedSafeExecutor = null;
}
- if(bkExecutor != null) {
+ if (bkExecutor != null) {
try {
bkExecutor.shutdownNow();
bkExecutor.awaitTermination(5, TimeUnit.SECONDS);
@@ -394,7 +400,7 @@ public static MockZooKeeper createMockZooKeeper() throws Exception {
}
public static MockZooKeeper createMockZooKeeperGlobal() {
- return MockZooKeeper.newInstanceForGlobalZK(MoreExecutors.newDirectExecutorService());
+ return MockZooKeeper.newInstanceForGlobalZK(MoreExecutors.newDirectExecutorService());
}
public static NonClosableMockBookKeeper createMockBookKeeper(OrderedExecutor executor) throws Exception {
@@ -512,7 +518,7 @@ protected void setupDefaultTenantAndNamespace() throws Exception {
@DataProvider(name = "invalidPersistentPolicies")
public Object[][] incorrectPersistentPolicies() {
- return new Object[][] {
+ return new Object[][]{
{0, 0, 0},
{1, 0, 0},
{0, 0, 1},
@@ -541,7 +547,7 @@ protected void deleteNamespaceWithRetry(String ns, boolean force, PulsarAdmin ad
/**
* see {@link MockedPulsarServiceBaseTest#deleteNamespaceWithRetry(String, boolean, PulsarAdmin, Collection)}
*/
- public static void deleteNamespaceWithRetry(String ns, boolean force, PulsarAdmin admin, PulsarService...pulsars)
+ public static void deleteNamespaceWithRetry(String ns, boolean force, PulsarAdmin admin, PulsarService... pulsars)
throws Exception {
deleteNamespaceWithRetry(ns, force, admin, Arrays.asList(pulsars));
}
@@ -588,4 +594,44 @@ public static class ServiceProducer {
}
private static final Logger log = LoggerFactory.getLogger(MockedPulsarServiceBaseTest.class);
+
+
+ // EC certificate
+ protected static final String TLS_EC_TRUSTED_CERT_PATH =
+ getAbsolutePath("certificate-authority/ec/ca.cert.pem");
+ protected static final String TLS_EC_SERVER_KEY_PATH =
+ getAbsolutePath("certificate-authority/ec/server.key-pk8.pem");
+ protected static final String TLS_EC_SERVER_CERT_PATH =
+ getAbsolutePath("certificate-authority/ec/server.cert.pem");
+ protected static final String TLS_EC_BROKER_CLIENT_KEY_PATH =
+ getAbsolutePath("certificate-authority/ec/broker_client.key-pk8.pem");
+ protected static final String TLS_EC_BROKER_CLIENT_CERT_PATH =
+ getAbsolutePath("certificate-authority/ec/broker_client.cert.pem");
+ protected static final String TLS_EC_CLIENT_KEY_PATH =
+ getAbsolutePath("certificate-authority/ec/client.key-pk8.pem");
+ protected static final String TLS_EC_CLIENT_CERT_PATH =
+ getAbsolutePath("certificate-authority/ec/client.cert.pem");
+
+ // EC KeyStore
+ protected static final String TLS_EC_KS_SERVER_STORE =
+ getAbsolutePath("certificate-authority/ec/jks/server.keystore.jks");
+ protected static final String TLS_EC_KS_SERVER_PASS = "serverpw";
+ protected static final String TLS_EC_KS_BROKER_CLIENT_STORE =
+ getAbsolutePath("certificate-authority/ec/jks/broker_client.keystore.jks");
+ protected static final String TLS_EC_KS_BROKER_CLIENT_PASS = "brokerclientpw";
+ protected static final String TLS_EC_KS_CLIENT_STORE =
+ getAbsolutePath("certificate-authority/ec/jks/client.keystore.jks");
+ protected static final String TLS_EC_KS_CLIENT_PASS = "clientpw";
+ protected static final String TLS_EC_KS_TRUSTED_STORE =
+ getAbsolutePath("certificate-authority/ec/jks/ca.truststore.jks");
+ protected static final String TLS_EC_KS_TRUSTED_STORE_PASS = "rootpw";
+
+ public static String getAbsolutePath(String resourceName) {
+ // On Windows, URL#getPath might return a string that starts with a disk name, e.g. "/C:/"
+ // It's invalid to use this path to open a file, so we need to get the absolute path via File.
+ return new File(Resources.getResource(resourceName).getPath()).getAbsolutePath();
+
+ }
+
+ protected static final ObjectMapper mapper = new ObjectMapper();
}
diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/security/tls/ec/TlsWithECCertificateFileTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/security/tls/ec/TlsWithECCertificateFileTest.java
new file mode 100644
index 0000000000000..87823321487d2
--- /dev/null
+++ b/pulsar-broker/src/test/java/org/apache/pulsar/security/tls/ec/TlsWithECCertificateFileTest.java
@@ -0,0 +1,130 @@
+/**
+ * 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.pulsar.security.tls.ec;
+
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.UUID;
+import lombok.Cleanup;
+import lombok.SneakyThrows;
+import org.apache.pulsar.broker.auth.MockedPulsarServiceBaseTest;
+import org.apache.pulsar.client.admin.PulsarAdmin;
+import org.apache.pulsar.client.api.Consumer;
+import org.apache.pulsar.client.api.Message;
+import org.apache.pulsar.client.api.MessageId;
+import org.apache.pulsar.client.api.Producer;
+import org.apache.pulsar.client.api.PulsarClient;
+import org.apache.pulsar.client.api.PulsarClientException;
+import org.apache.pulsar.client.impl.auth.AuthenticationTls;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+
+@Test
+public class TlsWithECCertificateFileTest extends MockedPulsarServiceBaseTest {
+
+ @Override
+ protected void doInitConf() throws Exception {
+ super.doInitConf();
+ conf.setTlsEnabled(true);
+ conf.setBrokerServicePort(Optional.empty());
+ conf.setWebServicePort(Optional.empty());
+ conf.setTlsTrustCertsFilePath(TLS_EC_TRUSTED_CERT_PATH);
+ conf.setTlsCertificateFilePath(TLS_EC_SERVER_CERT_PATH);
+ conf.setTlsKeyFilePath(TLS_EC_SERVER_KEY_PATH);
+ conf.setBrokerClientTlsEnabled(true);
+ conf.setBrokerClientTrustCertsFilePath(TLS_EC_TRUSTED_CERT_PATH);
+ conf.setBrokerClientAuthenticationPlugin(AuthenticationTls.class.getName());
+ final Map brokerClientAuthParams = new HashMap<>();
+ brokerClientAuthParams.put("tlsCertFile", TLS_EC_BROKER_CLIENT_CERT_PATH);
+ brokerClientAuthParams.put("tlsKeyFile", TLS_EC_BROKER_CLIENT_KEY_PATH);
+ conf.setBrokerClientAuthenticationParameters(mapper.writeValueAsString(brokerClientAuthParams));
+ conf.setBrokerClientAuthenticationParameters(mapper.writeValueAsString(brokerClientAuthParams));
+ }
+
+ @BeforeClass(alwaysRun = true)
+ @Override
+ protected void setup() throws Exception {
+ init();
+ admin = pulsar.getAdminClient();
+ setupDefaultTenantAndNamespace();
+ }
+
+ @AfterClass(alwaysRun = true)
+ @Override
+ protected void cleanup() throws Exception {
+ internalCleanup();
+ }
+ @Test(expectedExceptions = PulsarClientException.class)
+ @SneakyThrows
+ public void testConnectionFailWithoutCertificate() {
+ @Cleanup final PulsarClient client = PulsarClient.builder()
+ .serviceUrl(pulsar.getBrokerServiceUrlTls())
+ .build();
+ @Cleanup final Producer producer = client.newProducer()
+ .topic("should_be_failed")
+ .create();
+ }
+
+
+ @Test
+ @SneakyThrows
+ public void testConnectionSuccessWithCertificate() {
+ final AuthenticationTls authentication = new AuthenticationTls(TLS_EC_CLIENT_CERT_PATH, TLS_EC_CLIENT_KEY_PATH);
+ final String topicName = "persistent://public/default/" + UUID.randomUUID();
+ final int testMsgNum = 10;
+ @Cleanup final PulsarAdmin admin = PulsarAdmin.builder()
+ .authentication(authentication)
+ .serviceHttpUrl(pulsar.getWebServiceAddressTls())
+ .tlsTrustCertsFilePath(TLS_EC_TRUSTED_CERT_PATH)
+ .build();
+ admin.topics().createNonPartitionedTopic(topicName);
+ admin.topics().createSubscription(topicName, "sub-1", MessageId.earliest);
+ @Cleanup final PulsarClient client = PulsarClient.builder()
+ .serviceUrl(pulsar.getBrokerServiceUrlTls())
+ .authentication(authentication)
+ .tlsTrustCertsFilePath(TLS_EC_TRUSTED_CERT_PATH)
+ .build();
+ @Cleanup final Producer producer = client.newProducer()
+ .topic(topicName)
+ .create();
+ @Cleanup final Consumer consumer = client.newConsumer()
+ .topic(topicName)
+ .subscriptionName("sub-1")
+ .consumerName("cons-1")
+ .subscribe();
+ for (int i = 0; i < testMsgNum; i++) {
+ producer.send((i + "").getBytes(StandardCharsets.UTF_8));
+ }
+
+ for (int i = 0; i < testMsgNum; i++) {
+ final Message message = consumer.receive();
+ assertNotNull(message);
+ final byte[] b = message.getValue();
+ final String s = new String(b, StandardCharsets.UTF_8);
+ assertEquals(s, i + "");
+ }
+ }
+}
diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/security/tls/ec/TlsWithECKeyStoreTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/security/tls/ec/TlsWithECKeyStoreTest.java
new file mode 100644
index 0000000000000..cd841c13bf675
--- /dev/null
+++ b/pulsar-broker/src/test/java/org/apache/pulsar/security/tls/ec/TlsWithECKeyStoreTest.java
@@ -0,0 +1,141 @@
+/**
+ * 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.pulsar.security.tls.ec;
+
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import lombok.Cleanup;
+import lombok.SneakyThrows;
+import org.apache.pulsar.broker.auth.MockedPulsarServiceBaseTest;
+import org.apache.pulsar.client.admin.PulsarAdmin;
+import org.apache.pulsar.client.api.Consumer;
+import org.apache.pulsar.client.api.Message;
+import org.apache.pulsar.client.api.MessageId;
+import org.apache.pulsar.client.api.Producer;
+import org.apache.pulsar.client.api.PulsarClient;
+import org.apache.pulsar.client.api.PulsarClientException;
+import org.apache.pulsar.client.impl.auth.AuthenticationKeyStoreTls;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.UUID;
+
+
+@Test
+public class TlsWithECKeyStoreTest extends MockedPulsarServiceBaseTest {
+ @Override
+ protected void doInitConf() throws Exception {
+ super.doInitConf();
+ conf.setTlsEnabled(true);
+ conf.setBrokerServicePort(Optional.empty());
+ conf.setWebServicePort(Optional.empty());
+ conf.setTlsEnabledWithKeyStore(true);
+ conf.setTlsKeyStore(TLS_EC_KS_SERVER_STORE);
+ conf.setTlsKeyStorePassword(TLS_EC_KS_SERVER_PASS);
+ conf.setTlsTrustStore(TLS_EC_KS_TRUSTED_STORE);
+ conf.setTlsTrustStorePassword(TLS_EC_KS_TRUSTED_STORE_PASS);
+ conf.setTlsRequireTrustedClientCertOnConnect(true);
+ conf.setBrokerClientTlsEnabled(true);
+ conf.setBrokerClientTlsEnabledWithKeyStore(true);
+ conf.setBrokerClientTlsTrustStore(TLS_EC_KS_TRUSTED_STORE);
+ conf.setBrokerClientTlsTrustStorePassword(TLS_EC_KS_TRUSTED_STORE_PASS);
+ conf.setBrokerClientAuthenticationPlugin(AuthenticationKeyStoreTls.class.getName());
+ final Map brokerClientAuthParams = new HashMap<>();
+ brokerClientAuthParams.put("keyStorePath", TLS_EC_KS_BROKER_CLIENT_STORE);
+ brokerClientAuthParams.put("keyStorePassword", TLS_EC_KS_BROKER_CLIENT_PASS);
+ conf.setBrokerClientAuthenticationParameters(mapper.writeValueAsString(brokerClientAuthParams));
+ }
+
+ @BeforeClass(alwaysRun = true)
+ @Override
+ protected void setup() throws Exception {
+ init();
+ admin = pulsar.getAdminClient();
+ setupDefaultTenantAndNamespace();
+ }
+
+ @AfterClass(alwaysRun = true)
+ @Override
+ protected void cleanup() throws Exception {
+ internalCleanup();
+ }
+
+ @Test(expectedExceptions = PulsarClientException.class)
+ @SneakyThrows
+ public void testConnectionFailWithoutCertificate() {
+ @Cleanup final PulsarClient client = PulsarClient.builder()
+ .serviceUrl(pulsar.getBrokerServiceUrlTls())
+ .build();
+ @Cleanup final Producer producer = client.newProducer()
+ .topic("should_be_failed")
+ .create();
+ }
+
+
+ @Test
+ @SneakyThrows
+ public void testConnectionSuccessWithCertificate() {
+ final String topicName = "persistent://public/default/" + UUID.randomUUID();
+ final int testMsgNum = 10;
+ final Map clientAuthParams = new HashMap<>();
+ clientAuthParams.put("keyStorePath", TLS_EC_KS_CLIENT_STORE);
+ clientAuthParams.put("keyStorePassword", TLS_EC_KS_CLIENT_PASS);
+ @Cleanup final PulsarAdmin admin = PulsarAdmin.builder()
+ .useKeyStoreTls(true)
+ .tlsTrustStorePath(TLS_EC_KS_TRUSTED_STORE)
+ .tlsTrustStorePassword(TLS_EC_KS_TRUSTED_STORE_PASS)
+ .authentication(AuthenticationKeyStoreTls.class.getName(), mapper.writeValueAsString(clientAuthParams))
+ .serviceHttpUrl(pulsar.getWebServiceAddressTls())
+ .build();
+ admin.topics().createNonPartitionedTopic(topicName);
+ admin.topics().createSubscription(topicName, "sub-1", MessageId.earliest);
+ @Cleanup final PulsarClient client = PulsarClient.builder()
+ .serviceUrl(pulsar.getBrokerServiceUrlTls())
+ .useKeyStoreTls(true)
+ .tlsTrustStorePath(TLS_EC_KS_TRUSTED_STORE)
+ .tlsTrustStorePassword(TLS_EC_KS_TRUSTED_STORE_PASS)
+ .authentication(AuthenticationKeyStoreTls.class.getName(), mapper.writeValueAsString(clientAuthParams))
+ .build();
+ @Cleanup final Producer producer = client.newProducer()
+ .topic(topicName)
+ .create();
+ @Cleanup final Consumer consumer = client.newConsumer()
+ .topic(topicName)
+ .subscriptionName("sub-1")
+ .consumerName("cons-1")
+ .subscribe();
+ for (int i = 0; i < testMsgNum; i++) {
+ producer.send((i + "").getBytes(StandardCharsets.UTF_8));
+ }
+
+ for (int i = 0; i < testMsgNum; i++) {
+ final Message message = consumer.receive();
+ assertNotNull(message);
+ final byte[] b = message.getValue();
+ final String s = new String(b, StandardCharsets.UTF_8);
+ assertEquals(s, i + "");
+ }
+ }
+
+}
diff --git a/pulsar-common/src/main/java/org/apache/pulsar/common/util/SecurityUtility.java b/pulsar-common/src/main/java/org/apache/pulsar/common/util/SecurityUtility.java
index c288c054bb9f2..caa12f20b1be3 100644
--- a/pulsar-common/src/main/java/org/apache/pulsar/common/util/SecurityUtility.java
+++ b/pulsar-common/src/main/java/org/apache/pulsar/common/util/SecurityUtility.java
@@ -48,10 +48,14 @@
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
+import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Base64;
import java.util.Collection;
+import java.util.List;
import java.util.Set;
import java.util.concurrent.ScheduledExecutorService;
import javax.net.ssl.HostnameVerifier;
@@ -79,6 +83,10 @@ public class SecurityUtility {
public static final String BC_NON_FIPS_PROVIDER_CLASS = "org.bouncycastle.jce.provider.BouncyCastleProvider";
public static final String CONSCRYPT_PROVIDER_CLASS = "org.conscrypt.OpenSSLProvider";
public static final Provider CONSCRYPT_PROVIDER = loadConscryptProvider();
+ private static final List KEY_FACTORIES = Arrays.asList(
+ createKeyFactory("RSA"),
+ createKeyFactory("EC")
+ );
// Security.getProvider("BC") / Security.getProvider("BCFIPS").
// also used to get Factories. e.g. CertificateFactory.getInstance("X.509", "BCFIPS")
@@ -504,15 +512,21 @@ public static PrivateKey loadPrivateKeyFromPemStream(InputStream inStream) throw
while ((currentLine = reader.readLine()) != null && !currentLine.startsWith("-----END")) {
sb.append(currentLine);
}
-
- KeyFactory kf = KeyFactory.getInstance("RSA");
- KeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(sb.toString()));
- privateKey = kf.generatePrivate(keySpec);
- } catch (GeneralSecurityException | IOException e) {
+ final KeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(sb.toString()));
+ final List failedAlgorithm = new ArrayList<>(KEY_FACTORIES.size());
+ for (KeyFactory kf : KEY_FACTORIES) {
+ try {
+ return kf.generatePrivate(keySpec);
+ } catch (InvalidKeySpecException ex) {
+ failedAlgorithm.add(kf.getAlgorithm());
+ }
+ }
+ throw new KeyManagementException("The private key algorithm is not supported. attempted: "
+ + StringUtils.join(failedAlgorithm, ","));
+ } catch (IOException e) {
throw new KeyManagementException("Private key loading error", e);
}
- return privateKey;
}
private static void setupTrustCerts(SslContextBuilder builder, boolean allowInsecureConnection,
@@ -573,4 +587,12 @@ public static Provider resolveProvider(String providerName) throws NoSuchAlgorit
return provider;
}
+
+ private static KeyFactory createKeyFactory(String algorithm) {
+ try {
+ return KeyFactory.getInstance(algorithm);
+ } catch (Exception e) {
+ throw new IllegalArgumentException(String.format("Illegal key factory algorithm " + algorithm), e);
+ }
+ }
}
diff --git a/tests/certificate-authority/ec/broker_client.cert.pem b/tests/certificate-authority/ec/broker_client.cert.pem
new file mode 100644
index 0000000000000..2993ed41ad9d6
--- /dev/null
+++ b/tests/certificate-authority/ec/broker_client.cert.pem
@@ -0,0 +1,9 @@
+-----BEGIN CERTIFICATE-----
+MIIBIjCBygIUSAxJKNrIEmn3SVyw5rcYhwhKulwwCgYIKoZIzj0EAwIwETEPMA0G
+A1UEAwwGQ0FSb290MB4XDTIzMTEyNDExNTE1M1oXDTMzMTEyMTExNTE1M1owGDEW
+MBQGA1UEAwwNYnJva2VyX2NsaWVudDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA
+BGxRL4naRhrTZ9T2WdMBkCNmiamkrzEiDO55RVjhpHGWIoqPOvzs8i97vCVx39GV
+vV/9agDp2nSuXYW8ax3UKnkwCgYIKoZIzj0EAwIDRwAwRAIge8qxnGgmv5h+Yw3Y
+Ab/6xFD5QWERGMlfIl4ZCO3o6S0CICS/4jj45GfAPZS9QPfuo15rEa9Rbvvmmi+K
+yY0JA0SP
+-----END CERTIFICATE-----
diff --git a/tests/certificate-authority/ec/broker_client.csr.pem b/tests/certificate-authority/ec/broker_client.csr.pem
new file mode 100644
index 0000000000000..1f10a3c77f2b6
--- /dev/null
+++ b/tests/certificate-authority/ec/broker_client.csr.pem
@@ -0,0 +1,7 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIHTMHoCAQAwGDEWMBQGA1UEAwwNYnJva2VyX2NsaWVudDBZMBMGByqGSM49AgEG
+CCqGSM49AwEHA0IABGxRL4naRhrTZ9T2WdMBkCNmiamkrzEiDO55RVjhpHGWIoqP
+Ovzs8i97vCVx39GVvV/9agDp2nSuXYW8ax3UKnmgADAKBggqhkjOPQQDAgNJADBG
+AiEA8sGFcbQuUGIUTCXTQ0z9b0eIYFIDVOcGSInQ+0unMJMCIQCmH0GlXZRGB2lx
+HtfIz76HNnVu153LsHE11AEx7d/j2g==
+-----END CERTIFICATE REQUEST-----
diff --git a/tests/certificate-authority/ec/broker_client.key-pk8.pem b/tests/certificate-authority/ec/broker_client.key-pk8.pem
new file mode 100644
index 0000000000000..124073b024564
--- /dev/null
+++ b/tests/certificate-authority/ec/broker_client.key-pk8.pem
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgA92tkFXxKHYUJbeB
+vvnMaGBnP2IenpF66Fikb06xbUKhRANCAARsUS+J2kYa02fU9lnTAZAjZomppK8x
+IgzueUVY4aRxliKKjzr87PIve7wlcd/Rlb1f/WoA6dp0rl2FvGsd1Cp5
+-----END PRIVATE KEY-----
diff --git a/tests/certificate-authority/ec/broker_client.key.pem b/tests/certificate-authority/ec/broker_client.key.pem
new file mode 100644
index 0000000000000..4d4b5163b1bb4
--- /dev/null
+++ b/tests/certificate-authority/ec/broker_client.key.pem
@@ -0,0 +1,8 @@
+-----BEGIN EC PARAMETERS-----
+BggqhkjOPQMBBw==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIAPdrZBV8Sh2FCW3gb75zGhgZz9iHp6ReuhYpG9OsW1CoAoGCCqGSM49
+AwEHoUQDQgAEbFEvidpGGtNn1PZZ0wGQI2aJqaSvMSIM7nlFWOGkcZYiio86/Ozy
+L3u8JXHf0ZW9X/1qAOnadK5dhbxrHdQqeQ==
+-----END EC PRIVATE KEY-----
diff --git a/tests/certificate-authority/ec/ca.cert.pem b/tests/certificate-authority/ec/ca.cert.pem
new file mode 100644
index 0000000000000..c10385d997e86
--- /dev/null
+++ b/tests/certificate-authority/ec/ca.cert.pem
@@ -0,0 +1,10 @@
+-----BEGIN CERTIFICATE-----
+MIIBeDCCAR2gAwIBAgIUKRGzcPm3RVuI7tXdPDAZZ7Vhqs8wCgYIKoZIzj0EAwIw
+ETEPMA0GA1UEAwwGQ0FSb290MB4XDTIzMTEyNDExNTExNVoXDTMzMTEyMTExNTEx
+NVowETEPMA0GA1UEAwwGQ0FSb290MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
+kOKZaL45B7PUB+G25GLP1PPfTkio/DaHUML+KJjxpdCnSmq+mt/EAQWlqNPB1hJv
+6kOJ52vSxKe02BMeuROed6NTMFEwHQYDVR0OBBYEFDkqfvrnJ7PJhxJ7FTA7o8+b
+f+CRMB8GA1UdIwQYMBaAFDkqfvrnJ7PJhxJ7FTA7o8+bf+CRMA8GA1UdEwEB/wQF
+MAMBAf8wCgYIKoZIzj0EAwIDSQAwRgIhAN9+TWNNbIz8rMdkf4LGoIeQzYcAEyGJ
+90ORM5JciBdaAiEA8UsuQBD4wO1t6plnRydkGMTeb1dNDEnhsuXOXBps8fE=
+-----END CERTIFICATE-----
diff --git a/tests/certificate-authority/ec/ca.cert.srl b/tests/certificate-authority/ec/ca.cert.srl
new file mode 100644
index 0000000000000..a30f44e979e72
--- /dev/null
+++ b/tests/certificate-authority/ec/ca.cert.srl
@@ -0,0 +1 @@
+480C4928DAC81269F7495CB0E6B71887084ABA5D
diff --git a/tests/certificate-authority/ec/ca.key.pem b/tests/certificate-authority/ec/ca.key.pem
new file mode 100644
index 0000000000000..1255354584869
--- /dev/null
+++ b/tests/certificate-authority/ec/ca.key.pem
@@ -0,0 +1,8 @@
+-----BEGIN EC PARAMETERS-----
+BggqhkjOPQMBBw==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIPT1Jap2sJ7NUGWT6q0fnSRoVRNNryWe/JHPwttyQke4oAoGCCqGSM49
+AwEHoUQDQgAEkOKZaL45B7PUB+G25GLP1PPfTkio/DaHUML+KJjxpdCnSmq+mt/E
+AQWlqNPB1hJv6kOJ52vSxKe02BMeuROedw==
+-----END EC PRIVATE KEY-----
diff --git a/tests/certificate-authority/ec/certificate_generation.txt b/tests/certificate-authority/ec/certificate_generation.txt
new file mode 100644
index 0000000000000..7a6caa7b8f4be
--- /dev/null
+++ b/tests/certificate-authority/ec/certificate_generation.txt
@@ -0,0 +1,34 @@
+# CA Private Key
+openssl ecparam -name secp256r1 -genkey -out ca.key.pem
+# Request certificate
+openssl req -x509 -new -nodes -key ca.key.pem -subj "/CN=CARoot" -days 3650 -out ca.cert.pem
+
+# Server Private Key
+openssl ecparam -name secp256r1 -genkey -out server.key.pem
+# Convert to pkcs8
+openssl pkcs8 -topk8 -inform PEM -outform PEM -in server.key.pem -out server.key-pk8.pem -nocrypt
+# Request certificate
+openssl req -new -config server.conf -key server.key.pem -out server.csr.pem -sha256
+# Sign with CA
+openssl x509 -req -in server.csr.pem -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -out server.cert.pem -days 3650 -extensions v3_ext -extfile server.conf -sha256
+
+# Broker internal client Private Key
+openssl ecparam -name secp256r1 -genkey -out broker_client.key.pem
+# Convert to pkcs8
+openssl pkcs8 -topk8 -inform PEM -outform PEM -in broker_client.key.pem -out broker_client.key-pk8.pem -nocrypt
+# Request certificate
+openssl req -new -subj "/CN=broker_client" -key broker_client.key.pem -out broker_client.csr.pem -sha256
+# Sign with CA
+openssl x509 -req -in broker_client.csr.pem -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -out broker_client.cert.pem -days 3650 -sha256
+
+
+# Client Private Key
+openssl ecparam -name secp256r1 -genkey -out client.key.pem
+# Convert to pkcs8
+openssl pkcs8 -topk8 -inform PEM -outform PEM -in client.key.pem -out client.key-pk8.pem -nocrypt
+# Request certificate
+openssl req -new -subj "/CN=client" -key client.key.pem -out client.csr.pem -sha256
+# Sign with CA
+openssl x509 -req -in client.csr.pem -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -out client.cert.pem -days 3650 -sha256
+
+
diff --git a/tests/certificate-authority/ec/client.cert.pem b/tests/certificate-authority/ec/client.cert.pem
new file mode 100644
index 0000000000000..87701a6938d25
--- /dev/null
+++ b/tests/certificate-authority/ec/client.cert.pem
@@ -0,0 +1,8 @@
+-----BEGIN CERTIFICATE-----
+MIIBHDCBwwIUSAxJKNrIEmn3SVyw5rcYhwhKul0wCgYIKoZIzj0EAwIwETEPMA0G
+A1UEAwwGQ0FSb290MB4XDTIzMTEyNDExNTIwNVoXDTMzMTEyMTExNTIwNVowETEP
+MA0GA1UEAwwGY2xpZW50MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4QZJuqZS
+mSDbjkoFGKvtYmSVaJ3IjtmgWsgQio4F5phIXpM6IZZfcLkJToY0b9W2jGhODK55
+jA+zkRxHrICkwTAKBggqhkjOPQQDAgNIADBFAiEA0iGNqg4t16SxFdZJu7o9gK8R
+XVXphQ/9XAtw4XqfCUYCIGLoExE9XKdkzZ+sahFOpKD6YLZ1GgPRBPpBJFBGTYu7
+-----END CERTIFICATE-----
diff --git a/tests/certificate-authority/ec/client.csr.pem b/tests/certificate-authority/ec/client.csr.pem
new file mode 100644
index 0000000000000..4ec08d410f504
--- /dev/null
+++ b/tests/certificate-authority/ec/client.csr.pem
@@ -0,0 +1,7 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIHLMHMCAQAwETEPMA0GA1UEAwwGY2xpZW50MFkwEwYHKoZIzj0CAQYIKoZIzj0D
+AQcDQgAE4QZJuqZSmSDbjkoFGKvtYmSVaJ3IjtmgWsgQio4F5phIXpM6IZZfcLkJ
+ToY0b9W2jGhODK55jA+zkRxHrICkwaAAMAoGCCqGSM49BAMCA0gAMEUCIQDNZOBD
+Z/YAWKEeRSVqhPvIpFYob1gmQfDcBJdG8e0K8wIgcfO0PLquIZP9P8VrDkkLQdZ9
+krOKk+F/LF9aqQBHTbU=
+-----END CERTIFICATE REQUEST-----
diff --git a/tests/certificate-authority/ec/client.key-pk8.pem b/tests/certificate-authority/ec/client.key-pk8.pem
new file mode 100644
index 0000000000000..2b07827f21472
--- /dev/null
+++ b/tests/certificate-authority/ec/client.key-pk8.pem
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgrC3O+TuZ82b1bD1M
+SI9lMu6aaebqfoggcnaaAyUUstKhRANCAAThBkm6plKZINuOSgUYq+1iZJVonciO
+2aBayBCKjgXmmEhekzohll9wuQlOhjRv1baMaE4MrnmMD7ORHEesgKTB
+-----END PRIVATE KEY-----
diff --git a/tests/certificate-authority/ec/client.key.pem b/tests/certificate-authority/ec/client.key.pem
new file mode 100644
index 0000000000000..ac1207fa51c0b
--- /dev/null
+++ b/tests/certificate-authority/ec/client.key.pem
@@ -0,0 +1,8 @@
+-----BEGIN EC PARAMETERS-----
+BggqhkjOPQMBBw==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIKwtzvk7mfNm9Ww9TEiPZTLummnm6n6IIHJ2mgMlFLLSoAoGCCqGSM49
+AwEHoUQDQgAE4QZJuqZSmSDbjkoFGKvtYmSVaJ3IjtmgWsgQio4F5phIXpM6IZZf
+cLkJToY0b9W2jGhODK55jA+zkRxHrICkwQ==
+-----END EC PRIVATE KEY-----
diff --git a/tests/certificate-authority/ec/jks/broker_client.cert.pem b/tests/certificate-authority/ec/jks/broker_client.cert.pem
new file mode 100644
index 0000000000000..8a12e941d4e43
--- /dev/null
+++ b/tests/certificate-authority/ec/jks/broker_client.cert.pem
@@ -0,0 +1,10 @@
+-----BEGIN NEW CERTIFICATE REQUEST-----
+MIIBXjCCAQQCAQAwcjEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93
+bjEQMA4GA1UEBxMHVW5rbm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMH
+VW5rbm93bjEWMBQGA1UEAwwNYnJva2VyX2NsaWVudDBZMBMGByqGSM49AgEGCCqG
+SM49AwEHA0IABNEOf45UIs53Va887xTFRkZlmCnJUwYeu50pEll1APUwcldIHMXY
+EqRqoTOcBtSRx4CpO9LMPFmyCS1E+afXnbKgMDAuBgkqhkiG9w0BCQ4xITAfMB0G
+A1UdDgQWBBQFrlAl1jTZMagQVrax+OLTDJAQujAKBggqhkjOPQQDAgNIADBFAiBA
+sgj2HrKwxCfoUbBIjYqRcLPRRVBsbYOGk4e2uFTZPwIhAN/AdQn786S/ebnwSUzR
+yPyKEH+Qspx9nB08sQNn9N6U
+-----END NEW CERTIFICATE REQUEST-----
diff --git a/tests/certificate-authority/ec/jks/broker_client.keystore.jks b/tests/certificate-authority/ec/jks/broker_client.keystore.jks
new file mode 100644
index 0000000000000..81ecf4497198c
Binary files /dev/null and b/tests/certificate-authority/ec/jks/broker_client.keystore.jks differ
diff --git a/tests/certificate-authority/ec/jks/broker_client.signed.cert.pem b/tests/certificate-authority/ec/jks/broker_client.signed.cert.pem
new file mode 100644
index 0000000000000..b91c69400c5d1
--- /dev/null
+++ b/tests/certificate-authority/ec/jks/broker_client.signed.cert.pem
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE-----
+MIIBfTCCASQCFAJ6wB27laA1BCNConaAQPValPtaMAoGCCqGSM49BAMCMBExDzAN
+BgNVBAMMBkNBUm9vdDAeFw0yMzExMjUwNzAzNTNaFw0zMzExMjIwNzAzNTNaMHIx
+EDAOBgNVBAYTB1Vua25vd24xEDAOBgNVBAgTB1Vua25vd24xEDAOBgNVBAcTB1Vu
+a25vd24xEDAOBgNVBAoTB1Vua25vd24xEDAOBgNVBAsTB1Vua25vd24xFjAUBgNV
+BAMMDWJyb2tlcl9jbGllbnQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATRDn+O
+VCLOd1WvPO8UxUZGZZgpyVMGHrudKRJZdQD1MHJXSBzF2BKkaqEznAbUkceAqTvS
+zDxZsgktRPmn152yMAoGCCqGSM49BAMCA0cAMEQCIArXdTOx19Nn/a6bsfTYurQW
+4cepF5VKKijEjzyV69/BAiBpg60QwoZeSmz6bmil2zSb65jXrTzwhLpUZckVuHKn
+og==
+-----END CERTIFICATE-----
diff --git a/tests/certificate-authority/ec/jks/ca.cert.pem b/tests/certificate-authority/ec/jks/ca.cert.pem
new file mode 100644
index 0000000000000..a235464be7064
--- /dev/null
+++ b/tests/certificate-authority/ec/jks/ca.cert.pem
@@ -0,0 +1,10 @@
+-----BEGIN CERTIFICATE-----
+MIIBdjCCAR2gAwIBAgIUfHm94cF84m6FrJVNywJI4qTGZAEwCgYIKoZIzj0EAwIw
+ETEPMA0GA1UEAwwGQ0FSb290MB4XDTIzMTEyNTAxMzQzM1oXDTMzMTEyMjAxMzQz
+M1owETEPMA0GA1UEAwwGQ0FSb290MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
+Sxvkij8HQ+g07SnOLz1in81iGKY7lOAbJ1r4ihMVnOVjS2A4ZVGXHM2wp5ZB9r3Y
+jPByBiaPApm/J17JwlXynqNTMFEwHQYDVR0OBBYEFKqDJwbgz0/Q3EKJ78OVJI5k
+8+RYMB8GA1UdIwQYMBaAFKqDJwbgz0/Q3EKJ78OVJI5k8+RYMA8GA1UdEwEB/wQF
+MAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIgEF9RiwV0oBh9x1AvLFPoK5nnUlJ+0MNE
+zz8Zw284zkICIDUZOPN/E7ZmTKzfoZ0EkxRrinEZ5M538aNbYFAUYoK+
+-----END CERTIFICATE-----
diff --git a/tests/certificate-authority/ec/jks/ca.cert.srl b/tests/certificate-authority/ec/jks/ca.cert.srl
new file mode 100644
index 0000000000000..c7b003ddff287
--- /dev/null
+++ b/tests/certificate-authority/ec/jks/ca.cert.srl
@@ -0,0 +1 @@
+027AC01DBB95A035042342A2768040F55A94FB5B
diff --git a/tests/certificate-authority/ec/jks/ca.key.pem b/tests/certificate-authority/ec/jks/ca.key.pem
new file mode 100644
index 0000000000000..57e595f139525
--- /dev/null
+++ b/tests/certificate-authority/ec/jks/ca.key.pem
@@ -0,0 +1,8 @@
+-----BEGIN EC PARAMETERS-----
+BggqhkjOPQMBBw==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIJ/5AX63GN8cadJUCa5Aza5592JS7go9TXNfYemS4Ku4oAoGCCqGSM49
+AwEHoUQDQgAESxvkij8HQ+g07SnOLz1in81iGKY7lOAbJ1r4ihMVnOVjS2A4ZVGX
+HM2wp5ZB9r3YjPByBiaPApm/J17JwlXyng==
+-----END EC PRIVATE KEY-----
diff --git a/tests/certificate-authority/ec/jks/ca.truststore.jks b/tests/certificate-authority/ec/jks/ca.truststore.jks
new file mode 100644
index 0000000000000..e2a667b21d6ac
Binary files /dev/null and b/tests/certificate-authority/ec/jks/ca.truststore.jks differ
diff --git a/tests/certificate-authority/ec/jks/client.cert.pem b/tests/certificate-authority/ec/jks/client.cert.pem
new file mode 100644
index 0000000000000..022e63c57e077
--- /dev/null
+++ b/tests/certificate-authority/ec/jks/client.cert.pem
@@ -0,0 +1,10 @@
+-----BEGIN NEW CERTIFICATE REQUEST-----
+MIIBVjCB/QIBADBrMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3du
+MRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdV
+bmtub3duMQ8wDQYDVQQDEwZjbGllbnQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC
+AARVggD+3riNuIAZs9O/7kA3z2jC1cKEyBvftGwhixWf5iywL2pjw8/j2fyZ7Ya1
+nl2gFGHy1uaQKYizURJX9kQcoDAwLgYJKoZIhvcNAQkOMSEwHzAdBgNVHQ4EFgQU
+OQskWj9xk/eM5xQQhsQcPKZWCjcwCgYIKoZIzj0EAwIDSAAwRQIgGoPhD18yLhqK
+fL9I2ailJ2+ijoxHxO8ZhMR/8rxrv/oCIQDJfWQQtbcMBuMJoIdVFomFmERdr/Ix
+wttK875kwsfRQQ==
+-----END NEW CERTIFICATE REQUEST-----
diff --git a/tests/certificate-authority/ec/jks/client.keystore.jks b/tests/certificate-authority/ec/jks/client.keystore.jks
new file mode 100644
index 0000000000000..cdca07eb2a43f
Binary files /dev/null and b/tests/certificate-authority/ec/jks/client.keystore.jks differ
diff --git a/tests/certificate-authority/ec/jks/client.signed.cert.pem b/tests/certificate-authority/ec/jks/client.signed.cert.pem
new file mode 100644
index 0000000000000..f0d8b87dbc662
--- /dev/null
+++ b/tests/certificate-authority/ec/jks/client.signed.cert.pem
@@ -0,0 +1,10 @@
+-----BEGIN CERTIFICATE-----
+MIIBdjCCAR0CFAJ6wB27laA1BCNConaAQPValPtbMAoGCCqGSM49BAMCMBExDzAN
+BgNVBAMMBkNBUm9vdDAeFw0yMzExMjUwNzAzNTdaFw0zMzExMjIwNzAzNTdaMGsx
+EDAOBgNVBAYTB1Vua25vd24xEDAOBgNVBAgTB1Vua25vd24xEDAOBgNVBAcTB1Vu
+a25vd24xEDAOBgNVBAoTB1Vua25vd24xEDAOBgNVBAsTB1Vua25vd24xDzANBgNV
+BAMTBmNsaWVudDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABFWCAP7euI24gBmz
+07/uQDfPaMLVwoTIG9+0bCGLFZ/mLLAvamPDz+PZ/JnthrWeXaAUYfLW5pApiLNR
+Elf2RBwwCgYIKoZIzj0EAwIDRwAwRAIgEOvnGOeS9KdZ301pMOqovNDxxr1Sd4hy
+rp9a3+3LBvECIBxzHQ/IZN8nt9eG9Cm8vikOlmI1AmvMIKmo1n/9NwGr
+-----END CERTIFICATE-----
diff --git a/tests/certificate-authority/ec/jks/key_store_generation.txt b/tests/certificate-authority/ec/jks/key_store_generation.txt
new file mode 100644
index 0000000000000..62c48e9a089f1
--- /dev/null
+++ b/tests/certificate-authority/ec/jks/key_store_generation.txt
@@ -0,0 +1,33 @@
+# CA Private Key
+openssl ecparam -name secp256r1 -genkey -out ca.key.pem
+# Request certificate
+openssl req -x509 -new -nodes -key ca.key.pem -subj "/CN=CARoot" -days 3650 -out ca.cert.pem
+# Build Trust Cert
+keytool -keystore ca.truststore.jks -alias ca -importcert -file ca.cert.pem -storepass rootpw -keypass rootpw -noprompt
+
+
+# Create server keystore
+keytool -keystore server.keystore.jks -alias server -keyalg EC -validity 3600 -genkey -storepass serverpw -keypass serverpw -dname 'CN=server,OU=Unknown,O=Unknown,L=Unknown,ST=Unknown,C=Unknown' -noprompt
+# Export the certificate from the keystore:
+keytool -keystore server.keystore.jks -alias server -certreq -file server.cert.pem -storepass serverpw -keypass serverpw -noprompt
+# Sign it with the CA:
+openssl x509 -req -in server.cert.pem -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -out server.signed.cert.pem -days 3650 -sha256
+# Import signed cert into key store
+keytool -keystore server.keystore.jks -alias ca -importcert -file ca.cert.pem -storepass serverpw -keypass serverpw -noprompt
+keytool -keystore server.keystore.jks -alias server -importcert -file server.signed.cert.pem -storepass serverpw -keypass serverpw -noprompt
+
+
+# Create broker client keystore
+keytool -keystore broker_client.keystore.jks -alias broker_client -keyalg EC -validity 3600 -genkey -storepass brokerclientpw -keypass brokerclientpw -dname 'CN=broker_client,OU=Unknown,O=Unknown,L=Unknown,ST=Unknown,C=Unknown' -noprompt
+keytool -keystore broker_client.keystore.jks -alias broker_client -certreq -file broker_client.cert.pem -storepass brokerclientpw -keypass brokerclientpw -noprompt
+openssl x509 -req -in broker_client.cert.pem -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -out broker_client.signed.cert.pem -days 3650 -sha256
+keytool -keystore broker_client.keystore.jks -alias ca -importcert -file ca.cert.pem -storepass brokerclientpw -keypass brokerclientpw -noprompt
+keytool -keystore broker_client.keystore.jks -alias broker_client -importcert -file broker_client.signed.cert.pem -storepass brokerclientpw -keypass brokerclientpw -noprompt
+
+
+# Create client keystore
+keytool -keystore client.keystore.jks -alias client -keyalg EC -validity 3600 -genkey -storepass clientpw -keypass clientpw -dname 'CN=client,OU=Unknown,O=Unknown,L=Unknown,ST=Unknown,C=Unknown' -noprompt
+keytool -keystore client.keystore.jks -alias client -certreq -file client.cert.pem -storepass clientpw -keypass clientpw -noprompt
+openssl x509 -req -in client.cert.pem -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -out client.signed.cert.pem -days 3650 -sha256
+keytool -keystore client.keystore.jks -alias ca -importcert -file ca.cert.pem -storepass clientpw -keypass clientpw -noprompt
+keytool -keystore client.keystore.jks -alias client -importcert -file client.signed.cert.pem -storepass clientpw -keypass clientpw -noprompt
\ No newline at end of file
diff --git a/tests/certificate-authority/ec/jks/server.cert.pem b/tests/certificate-authority/ec/jks/server.cert.pem
new file mode 100644
index 0000000000000..e63f822f13a99
--- /dev/null
+++ b/tests/certificate-authority/ec/jks/server.cert.pem
@@ -0,0 +1,10 @@
+-----BEGIN NEW CERTIFICATE REQUEST-----
+MIIBVzCB/QIBADBrMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3du
+MRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdV
+bmtub3duMQ8wDQYDVQQDEwZzZXJ2ZXIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC
+AAQ0HBuze29SNGa33jTMzNZ+i4ZmQtccZGrGR8SfJPJVENahKSqJnoLgfHmzjfya
+XyYr/uwP4LYIqrWw9nsYZmb+oDAwLgYJKoZIhvcNAQkOMSEwHzAdBgNVHQ4EFgQU
+af0LXo7UTDd+QWFpoEkvqJPs+I0wCgYIKoZIzj0EAwIDSQAwRgIhANzNFj7zWN22
+uiNcz1EUvD8HS9C7R6Fk6Ps5Z54RNTtDAiEAlcDLOkHcgehHBIi79sfC9ZFj0Acg
+kcDY79IQi1k4gsc=
+-----END NEW CERTIFICATE REQUEST-----
diff --git a/tests/certificate-authority/ec/jks/server.keystore.jks b/tests/certificate-authority/ec/jks/server.keystore.jks
new file mode 100644
index 0000000000000..25c9eb4d1b07f
Binary files /dev/null and b/tests/certificate-authority/ec/jks/server.keystore.jks differ
diff --git a/tests/certificate-authority/ec/jks/server.signed.cert.pem b/tests/certificate-authority/ec/jks/server.signed.cert.pem
new file mode 100644
index 0000000000000..79a09731735ee
--- /dev/null
+++ b/tests/certificate-authority/ec/jks/server.signed.cert.pem
@@ -0,0 +1,10 @@
+-----BEGIN CERTIFICATE-----
+MIIBdzCCAR0CFAJ6wB27laA1BCNConaAQPValPtQMAoGCCqGSM49BAMCMBExDzAN
+BgNVBAMMBkNBUm9vdDAeFw0yMzExMjUwMTQzMDRaFw0zMzExMjIwMTQzMDRaMGsx
+EDAOBgNVBAYTB1Vua25vd24xEDAOBgNVBAgTB1Vua25vd24xEDAOBgNVBAcTB1Vu
+a25vd24xEDAOBgNVBAoTB1Vua25vd24xEDAOBgNVBAsTB1Vua25vd24xDzANBgNV
+BAMTBnNlcnZlcjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABDQcG7N7b1I0Zrfe
+NMzM1n6LhmZC1xxkasZHxJ8k8lUQ1qEpKomeguB8ebON/JpfJiv+7A/gtgiqtbD2
+exhmZv4wCgYIKoZIzj0EAwIDSAAwRQIgG4IatfLHoaCGVPDxnYV3XkWzVJpAEdX6
+QIDYgmdogckCIQDpJJle7jw6PNA1o3nSZJ2o2GCOg9nmmNaKVBQfxL2E/g==
+-----END CERTIFICATE-----
diff --git a/tests/certificate-authority/ec/server.cert.pem b/tests/certificate-authority/ec/server.cert.pem
new file mode 100644
index 0000000000000..184aa882e2828
--- /dev/null
+++ b/tests/certificate-authority/ec/server.cert.pem
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIIB9DCCAZqgAwIBAgIUSAxJKNrIEmn3SVyw5rcYhwhKulswCgYIKoZIzj0EAwIw
+ETEPMA0GA1UEAwwGQ0FSb290MB4XDTIzMTEyNDExNTE0MloXDTMzMTEyMTExNTE0
+MlowETEPMA0GA1UEAwwGc2VydmVyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
+8xsai5lXx2Y7TbmzB1sZr2RunBOtzHFelNBmryjgkatf0yIEy9/cCmH+DvJfjvG1
+hfZDvnVFBPaoDFwgmvb26KOBzzCBzDBMBgNVHSMERTBDgBQ5Kn765yezyYcSexUw
+O6PPm3/gkaEVpBMwETEPMA0GA1UEAwwGQ0FSb290ghQpEbNw+bdFW4ju1d08MBln
+tWGqzzAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEF
+BQcDATAtBgNVHREEJjAkggZwdWxzYXKCDnB1bHNhci5kZWZhdWx0hwR/AAABhwTA
+qAECMB0GA1UdDgQWBBQe+uKXtB+I7vfU+mRAMvuNYbWJSTAKBggqhkjOPQQDAgNI
+ADBFAiEAlCUpm4I5F6+OPS/lEJKIEQJILHivB3lPYW/OgXlpq5UCIFuUVgYwQ2ca
+yildeQibDy/gbxLCFVzDtYrVKf7SZSK+
+-----END CERTIFICATE-----
diff --git a/tests/certificate-authority/ec/server.conf b/tests/certificate-authority/ec/server.conf
new file mode 100644
index 0000000000000..557c2c27202db
--- /dev/null
+++ b/tests/certificate-authority/ec/server.conf
@@ -0,0 +1,40 @@
+#
+# 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.
+#
+
+[ req ]
+default_bits = 2048
+prompt = no
+default_md = sha256
+distinguished_name = dn
+
+[ v3_ext ]
+authorityKeyIdentifier=keyid,issuer:always
+basicConstraints=CA:FALSE
+keyUsage=critical, digitalSignature, keyEncipherment
+extendedKeyUsage=serverAuth
+subjectAltName=@alt_names
+
+[ dn ]
+CN = server
+
+[ alt_names ]
+DNS.1 = pulsar
+DNS.2 = pulsar.default
+IP.1 = 127.0.0.1
+IP.2 = 192.168.1.2
diff --git a/tests/certificate-authority/ec/server.csr.pem b/tests/certificate-authority/ec/server.csr.pem
new file mode 100644
index 0000000000000..ac75bb2d1ff64
--- /dev/null
+++ b/tests/certificate-authority/ec/server.csr.pem
@@ -0,0 +1,7 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIHLMHMCAQAwETEPMA0GA1UEAwwGc2VydmVyMFkwEwYHKoZIzj0CAQYIKoZIzj0D
+AQcDQgAE8xsai5lXx2Y7TbmzB1sZr2RunBOtzHFelNBmryjgkatf0yIEy9/cCmH+
+DvJfjvG1hfZDvnVFBPaoDFwgmvb26KAAMAoGCCqGSM49BAMCA0gAMEUCIFUCpVkb
+5u0EEY/4zcXFTHahm4xq/GAziFZsGS3mjwncAiEA2RGraZwclbHwjBiIChd56Xim
+SHyZ2voxfe+xJG7uX8g=
+-----END CERTIFICATE REQUEST-----
diff --git a/tests/certificate-authority/ec/server.key-pk8.pem b/tests/certificate-authority/ec/server.key-pk8.pem
new file mode 100644
index 0000000000000..f30bd1cc58cc7
--- /dev/null
+++ b/tests/certificate-authority/ec/server.key-pk8.pem
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgnYGgcNz49WhMgVPD
+LmI1fYtfI/YqWDrd2jtnXFGNawShRANCAATzGxqLmVfHZjtNubMHWxmvZG6cE63M
+cV6U0GavKOCRq1/TIgTL39wKYf4O8l+O8bWF9kO+dUUE9qgMXCCa9vbo
+-----END PRIVATE KEY-----
diff --git a/tests/certificate-authority/ec/server.key.pem b/tests/certificate-authority/ec/server.key.pem
new file mode 100644
index 0000000000000..1725f1be43fb1
--- /dev/null
+++ b/tests/certificate-authority/ec/server.key.pem
@@ -0,0 +1,8 @@
+-----BEGIN EC PARAMETERS-----
+BggqhkjOPQMBBw==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIJ2BoHDc+PVoTIFTwy5iNX2LXyP2Klg63do7Z1xRjWsEoAoGCCqGSM49
+AwEHoUQDQgAE8xsai5lXx2Y7TbmzB1sZr2RunBOtzHFelNBmryjgkatf0yIEy9/c
+CmH+DvJfjvG1hfZDvnVFBPaoDFwgmvb26A==
+-----END EC PRIVATE KEY-----