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

zhaocong pushed a commit to branch branch-2.10.5.3-a41ecf
in repository https://gitbox.apache.org/repos/asf/pulsar.git

commit 7f3906c16971b4049637d8a85253ea83312980d2
Author: Qiang Zhao <[email protected]>
AuthorDate: Mon Nov 27 20:08:39 2023 +0800

    [improve][sec] Support for Elliptic Curve Cryptography (EC, ECC) 
(certificates/private keys) (#21621)
    
    (cherry picked from commit e1d06b5f54f08c09debab7a9a513b7c173c1779b)
---
 pom.xml                                            |   2 +
 .../broker/auth/MockedPulsarServiceBaseTest.java   |  57 ++++++++-
 .../tls/ec/TlsWithECCertificateFileTest.java       | 130 +++++++++++++++++++
 .../security/tls/ec/TlsWithECKeyStoreTest.java     | 141 +++++++++++++++++++++
 .../apache/pulsar/common/util/SecurityUtility.java |  34 ++++-
 .../ec/broker_client.cert.pem                      |   9 ++
 .../certificate-authority/ec/broker_client.csr.pem |   7 +
 .../ec/broker_client.key-pk8.pem                   |   5 +
 .../certificate-authority/ec/broker_client.key.pem |   8 ++
 tests/certificate-authority/ec/ca.cert.pem         |  10 ++
 tests/certificate-authority/ec/ca.cert.srl         |   1 +
 tests/certificate-authority/ec/ca.key.pem          |   8 ++
 .../ec/certificate_generation.txt                  |  34 +++++
 tests/certificate-authority/ec/client.cert.pem     |   8 ++
 tests/certificate-authority/ec/client.csr.pem      |   7 +
 tests/certificate-authority/ec/client.key-pk8.pem  |   5 +
 tests/certificate-authority/ec/client.key.pem      |   8 ++
 .../ec/jks/broker_client.cert.pem                  |  10 ++
 .../ec/jks/broker_client.keystore.jks              | Bin 0 -> 2034 bytes
 .../ec/jks/broker_client.signed.cert.pem           |  11 ++
 tests/certificate-authority/ec/jks/ca.cert.pem     |  10 ++
 tests/certificate-authority/ec/jks/ca.cert.srl     |   1 +
 tests/certificate-authority/ec/jks/ca.key.pem      |   8 ++
 .../certificate-authority/ec/jks/ca.truststore.jks | Bin 0 -> 742 bytes
 tests/certificate-authority/ec/jks/client.cert.pem |  10 ++
 .../ec/jks/client.keystore.jks                     | Bin 0 -> 1988 bytes
 .../ec/jks/client.signed.cert.pem                  |  10 ++
 .../ec/jks/key_store_generation.txt                |  33 +++++
 tests/certificate-authority/ec/jks/server.cert.pem |  10 ++
 .../ec/jks/server.keystore.jks                     | Bin 0 -> 2004 bytes
 .../ec/jks/server.signed.cert.pem                  |  10 ++
 tests/certificate-authority/ec/server.cert.pem     |  13 ++
 tests/certificate-authority/ec/server.conf         |  40 ++++++
 tests/certificate-authority/ec/server.csr.pem      |   7 +
 tests/certificate-authority/ec/server.key-pk8.pem  |   5 +
 tests/certificate-authority/ec/server.key.pem      |   8 ++
 36 files changed, 648 insertions(+), 12 deletions(-)

diff --git a/pom.xml b/pom.xml
index 9f71cab2f22..07081b8aab9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1488,6 +1488,8 @@ flexible messaging model and an intuitive client 
API.</description>
             <exclude>**/*.crt</exclude>
             <exclude>**/*.key</exclude>
             <exclude>**/*.csr</exclude>
+            <exclude>**/*.srl</exclude>
+            <exclude>**/*.txt</exclude>
             <exclude>**/*.pem</exclude>
             <exclude>**/*.json</exclude>
             <exclude>**/*.htpasswd</exclude>
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 c1f75ba141d..17b14d770f6 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,8 +25,11 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 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;
@@ -42,6 +45,7 @@ import java.util.Set;
 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;
@@ -73,6 +77,7 @@ import org.apache.zookeeper.data.ACL;
 import org.awaitility.Awaitility;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper;
 import org.testng.annotations.DataProvider;
 
 /**
@@ -88,7 +93,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;
 
@@ -229,7 +234,7 @@ public abstract class MockedPulsarServiceBaseTest extends 
TestRetrySupport {
             mockZooKeeper.shutdown();
             mockZooKeeper = null;
         }
-        if(sameThreadOrderedSafeExecutor != null) {
+        if (sameThreadOrderedSafeExecutor != null) {
             try {
                 sameThreadOrderedSafeExecutor.shutdownNow();
                 sameThreadOrderedSafeExecutor.awaitTermination(5, 
TimeUnit.SECONDS);
@@ -239,7 +244,7 @@ public abstract class MockedPulsarServiceBaseTest extends 
TestRetrySupport {
             }
             sameThreadOrderedSafeExecutor = null;
         }
-        if(bkExecutor != null) {
+        if (bkExecutor != null) {
             try {
                 bkExecutor.shutdownNow();
                 bkExecutor.awaitTermination(5, TimeUnit.SECONDS);
@@ -388,7 +393,7 @@ public abstract class MockedPulsarServiceBaseTest extends 
TestRetrySupport {
     }
 
     public static MockZooKeeper createMockZooKeeperGlobal() {
-        return  
MockZooKeeper.newInstanceForGlobalZK(MoreExecutors.newDirectExecutorService());
+        return 
MockZooKeeper.newInstanceForGlobalZK(MoreExecutors.newDirectExecutorService());
     }
 
     public static NonClosableMockBookKeeper 
createMockBookKeeper(OrderedExecutor executor) throws Exception {
@@ -506,7 +511,7 @@ public abstract class MockedPulsarServiceBaseTest extends 
TestRetrySupport {
 
     @DataProvider(name = "invalidPersistentPolicies")
     public Object[][] incorrectPersistentPolicies() {
-        return new Object[][] {
+        return new Object[][]{
                 {0, 0, 0},
                 {1, 0, 0},
                 {0, 0, 1},
@@ -535,7 +540,7 @@ public abstract class MockedPulsarServiceBaseTest extends 
TestRetrySupport {
     /**
      * 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));
     }
@@ -564,4 +569,44 @@ public abstract class MockedPulsarServiceBaseTest extends 
TestRetrySupport {
     }
 
     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 00000000000..87823321487
--- /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<String, String> 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<byte[]> 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<byte[]> producer = client.newProducer()
+                .topic(topicName)
+                .create();
+        @Cleanup final Consumer<byte[]> 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<byte[]> 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 00000000000..cd841c13bf6
--- /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<String, String> 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<byte[]> 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<String, String> 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<byte[]> producer = client.newProducer()
+                .topic(topicName)
+                .create();
+        @Cleanup final Consumer<byte[]> 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<byte[]> 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 c288c054bb9..caa12f20b1b 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.Certificate;
 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<KeyFactory> 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 class SecurityUtility {
             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<String> 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 class SecurityUtility {
 
         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 00000000000..2993ed41ad9
--- /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 00000000000..1f10a3c77f2
--- /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 00000000000..124073b0245
--- /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 00000000000..4d4b5163b1b
--- /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 00000000000..c10385d997e
--- /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 00000000000..a30f44e979e
--- /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 00000000000..12553545848
--- /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 00000000000..7a6caa7b8f4
--- /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 00000000000..87701a6938d
--- /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 00000000000..4ec08d410f5
--- /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 00000000000..2b07827f214
--- /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 00000000000..ac1207fa51c
--- /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 00000000000..8a12e941d4e
--- /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 00000000000..81ecf449719
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 00000000000..b91c69400c5
--- /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 00000000000..a235464be70
--- /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 00000000000..c7b003ddff2
--- /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 00000000000..57e595f1395
--- /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 00000000000..e2a667b21d6
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 00000000000..022e63c57e0
--- /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 00000000000..cdca07eb2a4
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 00000000000..f0d8b87dbc6
--- /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 00000000000..62c48e9a089
--- /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 00000000000..e63f822f13a
--- /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 00000000000..25c9eb4d1b0
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 00000000000..79a09731735
--- /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 00000000000..184aa882e28
--- /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 00000000000..557c2c27202
--- /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 00000000000..ac75bb2d1ff
--- /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 00000000000..f30bd1cc58c
--- /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 00000000000..1725f1be43f
--- /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-----

Reply via email to