You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pulsar.apache.org by si...@apache.org on 2020/03/28 10:35:06 UTC

[pulsar] branch master updated: Support BouncyCastle FIPS provider (#6588)

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

sijie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar.git


The following commit(s) were added to refs/heads/master by this push:
     new 181e5e7  Support BouncyCastle FIPS provider  (#6588)
181e5e7 is described below

commit 181e5e7f585846c31d8500a4de449ef58ffcf794
Author: Jia Zhai <zh...@apache.org>
AuthorDate: Sat Mar 28 18:34:57 2020 +0800

    Support BouncyCastle FIPS provider  (#6588)
    
    ### Motivation
    
    Try to make user able to use both "org.bouncycastle.jce.provider.BouncyCastleProvider" and  "org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider".
    
    Current code, bouncycastle (bc) jars  are used in both broker and client, and are tied strongly in both broker and client.  We need to make it easy config. This change try to split bc and module that depends on it. Then user could freely include/exclude it.
    
    ### Changes
    - build a shaded jar for bouncycastle non-fips version. other module depends on this module.
    - build nar for both fips and non-fips version of bouncycastle, user could able to load bouncycastle by these 2 nar.
    - split MessageCrypto out from client and made it an individual module.  so client is able to exclude bouncycastle.
    - Add 2 test examples:  1, exclude bc-non-fips version, and include bc-fips version; 2, exclude bc-non-fips version and load bc-fips version by nar.
---
 .../bc-shaded}/pom.xml                             |  59 ++--
 .../bc}/LICENSE                                    | 352 +--------------------
 bouncy-castle/bc/pom.xml                           |  64 ++++
 .../apache/pulsar/bcloader/BouncyCastleLoader.java |  47 +++
 .../resources/META-INF/services/bouncy-castle.yaml |  22 ++
 bouncy-castle/bcfips-include-test/pom.xml          |  95 ++++++
 .../pulsar/client/TlsProducerConsumerBase.java     | 111 +++++++
 .../pulsar/client/TlsProducerConsumerTest.java     | 130 ++++++++
 .../resources/authentication/tls/broker-cert.pem   |  73 +++++
 .../resources/authentication/tls/broker-key.pem    |  28 ++
 .../test/resources/authentication/tls/cacert.pem   |  62 ++++
 .../resources/authentication/tls/client-cert.pem   |  73 +++++
 .../resources/authentication/tls/client-key.pem    |  28 ++
 bouncy-castle/bcfips-nar-test/pom.xml              | 102 ++++++
 .../pulsar/client/TlsProducerConsumerBase.java     | 129 ++++++++
 .../pulsar/client/TlsProducerConsumerTest.java     | 130 ++++++++
 .../resources/authentication/tls/broker-cert.pem   |  73 +++++
 .../resources/authentication/tls/broker-key.pem    |  28 ++
 .../test/resources/authentication/tls/cacert.pem   |  62 ++++
 .../resources/authentication/tls/client-cert.pem   |  73 +++++
 .../resources/authentication/tls/client-key.pem    |  28 ++
 .../bcfips}/LICENSE                                | 351 +-------------------
 bouncy-castle/bcfips/pom.xml                       |  64 ++++
 .../pulsar/bcloader/BouncyCastleFipsLoader.java    |  47 +++
 .../resources/META-INF/services/bouncy-castle.yaml |  22 ++
 bouncy-castle/pom.xml                              |  48 +++
 distribution/server/pom.xml                        |   5 +
 distribution/server/src/assemble/LICENSE.bin.txt   |   6 -
 pom.xml                                            |  18 +-
 pulsar-broker-shaded/pom.xml                       |   2 +
 pulsar-broker/pom.xml                              |   9 +-
 .../client/api/SimpleProducerConsumerTest.java     |  12 +-
 .../pulsar-client-2x-shaded/pom.xml                |   2 +-
 pulsar-client-admin-shaded/pom.xml                 |   2 +
 pulsar-client-all/pom.xml                          |   9 +
 pulsar-client-api/pom.xml                          |   7 +
 .../apache/pulsar/client/api/ConsumerBuilder.java  |  11 +
 .../apache/pulsar/client/api/MessageCrypto.java    |  81 +++++
 pulsar-client-messagecrypto-bc/pom.xml             |  51 +++
 .../pulsar/client/impl/crypto/MessageCryptoBc.java |  49 +--
 pulsar-client-shaded/pom.xml                       |  14 +-
 pulsar-client/pom.xml                              |  22 +-
 .../pulsar/client/impl/ConsumerBuilderImpl.java    |   7 +
 .../apache/pulsar/client/impl/ConsumerImpl.java    |  22 +-
 .../apache/pulsar/client/impl/ProducerImpl.java    |  35 +-
 .../pulsar/client/impl/auth/AuthenticationTls.java |  10 +-
 .../impl/conf/ConsumerConfigurationData.java       |   4 +
 .../impl/conf/ProducerConfigurationData.java       |   4 +
 pulsar-common/pom.xml                              |   5 -
 .../org/apache/pulsar/common/util/BCLoader.java    |  28 ++
 .../apache/pulsar/common/util/BcNarDefinition.java |  47 +++
 .../pulsar/common/util/SearchBcNarUtils.java       | 116 +++++++
 .../apache/pulsar/common/util/SecurityUtility.java |  72 ++++-
 pulsar-discovery-service/pom.xml                   |  10 +-
 pulsar-functions/worker/pom.xml                    |  15 +
 .../pulsar/proxy/server/ProxyServiceStarter.java   |   3 -
 pulsar-sql/presto-distribution/LICENSE             |   9 +-
 pulsar-testclient/pom.xml                          |   6 +
 site2/docs/security-bouncy-castle.md               | 121 +++++++
 site2/docs/security-tls-authentication.md          |   2 +
 site2/docs/security-tls-transport.md               |   2 +
 site2/website/sidebars.json                        |   3 +-
 62 files changed, 2296 insertions(+), 826 deletions(-)

diff --git a/pulsar-client-1x-base/pulsar-client-2x-shaded/pom.xml b/bouncy-castle/bc-shaded/pom.xml
similarity index 53%
copy from pulsar-client-1x-base/pulsar-client-2x-shaded/pom.xml
copy to bouncy-castle/bc-shaded/pom.xml
index 9a65ea5..7396895 100644
--- a/pulsar-client-1x-base/pulsar-client-2x-shaded/pom.xml
+++ b/bouncy-castle/bc-shaded/pom.xml
@@ -18,33 +18,32 @@
     under the License.
 
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
+    <artifactId>bouncy-castle-parent</artifactId>
     <groupId>org.apache.pulsar</groupId>
-    <artifactId>pulsar-client-1x-base</artifactId>
     <version>2.6.0-SNAPSHOT</version>
-    <relativePath>..</relativePath>
   </parent>
 
-  <artifactId>pulsar-client-2x-shaded</artifactId>
-  <name>Pulsar Client 2.x Shaded API</name>
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>bouncy-castle-bc-shaded</artifactId>
+  <packaging>jar</packaging>
+  <name>Apache Pulsar :: Bouncy Castle :: BC Shaded</name>
+  <version>2.6.0-SNAPSHOT</version>
 
   <dependencies>
     <dependency>
       <groupId>org.apache.pulsar</groupId>
-      <artifactId>pulsar-client</artifactId>
-      <version>${project.parent.version}</version>
+      <artifactId>bouncy-castle-bc</artifactId>
+      <version>2.6.0-SNAPSHOT</version>
+      <optional>true</optional>
     </dependency>
   </dependencies>
-  
+
+  <!--  build a fat jar that only includes bouncycastle for easy replace-->
   <build>
     <plugins>
-       <plugin>
-        <!-- Shade all the dependencies to avoid conflicts -->
-        <groupId>org.apache.maven.plugins</groupId>
+      <plugin>
         <artifactId>maven-shade-plugin</artifactId>
         <executions>
           <execution>
@@ -59,36 +58,28 @@
 
               <artifactSet>
                 <includes>
-                  <include>org.apache.pulsar:pulsar-client</include>
-                  <include>org.apache.pulsar:pulsar-client-api</include>
+                  <include>org.bouncycastle:*</include>
                 </includes>
               </artifactSet>
+
               <filters>
                 <filter>
-                  <artifact>org.apache.pulsar:pulsar-client</artifact>
-                  <includes>
-                    <include>**</include>
-                  </includes>
+                  <!-- Shading signed JARs will fail without
+                      this. http://stackoverflow.com/questions/999489/invalid-signature-file-when-attempting-to-run-a-jar -->
+                  <artifact>*:*</artifact>
+                  <excludes>
+                    <exclude>META-INF/*.SF</exclude>
+                    <exclude>META-INF/*.DSA</exclude>
+                    <exclude>META-INF/*.RSA</exclude>
+                  </excludes>
                 </filter>
               </filters>
-              <relocations>
-                <relocation>
-                  <pattern>org.apache.pulsar.client.api</pattern>
-                  <shadedPattern>org.apache.pulsar.shade.client.api.v2</shadedPattern>
-                  <includes>
-                    <include>org.apache.pulsar.client.api.PulsarClient</include>
-                    <include>org.apache.pulsar.client.api.Producer</include>
-                    <include>org.apache.pulsar.client.api.Consumer</include>
-                    <include>org.apache.pulsar.client.api.Reader</include>
-                    <include>org.apache.pulsar.client.api.MessageListener</include>
-                    <include>org.apache.pulsar.client.api.ReaderListener</include>
-                  </includes>
-                </relocation>
-              </relocations>
             </configuration>
           </execution>
         </executions>
       </plugin>
     </plugins>
   </build>
+
 </project>
+
diff --git a/pulsar-sql/presto-distribution/LICENSE b/bouncy-castle/bc/LICENSE
similarity index 54%
copy from pulsar-sql/presto-distribution/LICENSE
copy to bouncy-castle/bc/LICENSE
index e1d08d1..5921755 100644
--- a/pulsar-sql/presto-distribution/LICENSE
+++ b/bouncy-castle/bc/LICENSE
@@ -203,354 +203,8 @@
 ----------------------------------------------------------------------------------------------------
 
 This projects includes binary packages with the following licenses:
-
-The Apache Software License, Version 2.0
-
-  * Jackson
-    - jackson-annotations-2.8.11.jar
-    - jackson-core-2.8.11.jar
-    - jackson-databind-2.8.11.4.jar
-    - jackson-dataformat-smile-2.8.11.jar
-    - jackson-datatype-guava-2.8.11.jar
-    - jackson-datatype-guava-2.8.11.jar
-    - jackson-datatype-jdk8-2.8.11.jar
-    - jackson-datatype-jdk8-2.8.11.jar
-    - jackson-datatype-joda-2.8.11.jar
-    - jackson-datatype-jsr310-2.8.11.jar
-    - jackson-dataformat-yaml-2.8.11.jar
- * Guava
-    - guava-25.1-jre.jar
- * Google Guice
-    - guice-4.2.0.jar
-    - guice-multibindings-4.2.0.jar
- * Apache Commons
-    - commons-math3-3.6.1.jar
-    - commons-beanutils-core-1.8.3.jar
-    - commons-compress-1.19.jar
-    - commons-lang3-3.3.2.jar
-    - commons-lang3-3.4.jar
- * Netty
-    - netty-3.10.6.Final.jar
-    - netty-buffer-4.1.45.Final.jar
-    - netty-codec-4.1.45.Final.jar
-    - netty-codec-dns-4.1.45.Final.jar
-    - netty-codec-http-4.1.45.Final.jar
-    - netty-codec-socks-4.1.45.Final.jar
-    - netty-common-4.1.45.Final.jar
-    - netty-handler-4.1.45.Final.jar
-    - netty-handler-proxy-4.1.45.Final.jar
-    - netty-reactive-streams-2.0.0.jar
-    - netty-resolver-4.1.45.Final.jar
-    - netty-resolver-dns-4.1.45.Final.jar
-    - netty-tcnative-boringssl-static-2.0.26.Final.jar
-    - netty-transport-4.1.45.Final.jar
-    - netty-transport-native-epoll-4.1.45.Final.jar
-    - netty-transport-native-epoll-4.1.45.Final-linux-x86_64.jar
-    - netty-transport-native-unix-common-4.1.45.Final.jar
-    - netty-transport-native-unix-common-4.1.45.Final-linux-x86_64.jar
- * Joda Time
-    - joda-time-2.9.9.jar
-    - joda-time-2.10.1.jar
- * Jetty
-    - http2-client-9.4.11.v20180605.jar
-    - http2-common-9.4.11.v20180605.jar
-    - http2-hpack-9.4.11.v20180605.jar
-    - http2-http-client-transport-9.4.11.v20180605.jar
-    - http2-server-9.4.11.v20180605.jar
-    - jetty-alpn-client-9.4.11.v20180605.jar
-    - jetty-client-9.4.11.v20180605.jar
-    - jetty-http-9.4.11.v20180605.jar
-    - jetty-io-9.4.11.v20180605.jar
-    - jetty-jmx-9.4.11.v20180605.jar
-    - jetty-security-9.4.11.v20180605.jar
-    - jetty-server-9.4.11.v20180605.jar
-    - jetty-servlet-9.4.11.v20180605.jar
-    - jetty-util-9.4.11.v20180605.jar
-  * Asynchronous Http Client
-    - async-http-client-1.9.40.jar
-  * Apache BVal
-    - bval-core-1.1.1.jar
-    - bval-jsr-1.1.1.jar
-  * Bytecode
-    - bytecode-1.0.jar
-  * CGLIB Nodep
-    - cglib-nodep-3.2.5.jar
-  * Airlift
-    - aircompressor-0.11.jar
-    - airline-0.8.jar
-    - bootstrap-0.170.jar
-    - bootstrap-0.171.jar
-    - concurrent-0.171.jar
-    - configuration-0.171.jar
-    - configuration-0.170.jar
-    - discovery-0.171.jar
-    - discovery-server-1.29.jar
-    - event-0.171.jar
-    - http-client-0.171.jar
-    - http-server-0.171.jar
-    - jmx-0.171.jar
-    - jmx-http-0.171.jar
-    - jmx-http-rpc-0.159.jar
-    - joni-2.1.5.1.jar
-    - json-0.170.jar
-    - json-0.171.jar
-    - log-0.170.jar
-    - log-0.171.jar
-    - log-manager-0.170.jar
-    - log-manager-0.171.jar
-    - node-0.171.jar
-    - resolver-1.4.jar
-    - security-0.171.jar
-    - slice-0.35.jar
-    - stats-0.171.jar
-    - trace-token-0.171.jar
-    - units-1.0.jar
-  * Error Prone Annotations
-    - error_prone_annotations-2.1.3.jar
-  * Esri Geometry API For Java
-    - esri-geometry-api-2.1.0.jar
-  * Fastutil
-    - fastutil-6.5.9.jar
-  * J2ObjC Annotations
-    - j2objc-annotations-1.1.jar
-  * JSON Web Token Support For The JVM
-    - jjwt-0.9.0.jar
-  * Jmxutils
-    - jmxutils-1.19.jar
-  * LevelDB
-    - leveldb-0.10.jar
-    - leveldb-api-0.10.jar
-  * Log4j implemented over SLF4J
-    - log4j-over-slf4j-1.7.25.jar
-  * Lucene Common Analyzers
-    - lucene-analyzers-common-7.2.1.jar
-  * Maven
-    - maven-aether-provider-3.0.5.jar
-    - maven-artifact-3.0.5.jar
-    - maven-core-3.0.5.jar
-    - maven-compat-3.0.5.jar
-    - maven-embedder-3.0.5.jar
-    - maven-model-3.0.5.jar
-    - maven-model-builder-3.0.5.jar
-    - maven-plugin-api-3.0.5.jar
-    - maven-repository-metadata-3.0.5.jar
-    - maven-settings-3.0.5.jar
-    - maven-settings-builder-3.0.5.jar
-	- wagon-provider-api-2.4.jar
-  * OkHttp
-    - okhttp-3.9.0.jar
-    - okhttp-urlconnection-3.9.0.jar
-  * OpenCSV
-    - opencsv-2.3.jar
-  * Plexus
-    - plexus-cipher-1.7.jar
-    - plexus-classworlds-2.4.jar
-    - plexus-component-annotations-1.5.5.jar
-    - plexus-container-default-1.5.5.jar
-    - plexus-interpolation-1.14.jar
-    - plexus-sec-dispatcher-1.3.jar
-    - plexus-utils-2.0.6.jar
-  * Apache XBean :: Reflect
-    - xbean-reflect-3.4.jar
-  * Avro
-    - avro-1.9.1.jar
-    - avro-protobuf-1.9.1.jar
-  * Caffeine
-    - caffeine-2.6.2.jar
-  * Javax
-    - javax.inject-1.jar
-    - javax.inject-1.jar
-    - javax.servlet-api-3.1.0.jar
-    - javax.ws.rs-api-2.1.jar
-  * JCommander
-    - jcommander-1.48.jar
-  * FindBugs JSR305
-    - jsr305-3.0.2.jar
-  * Objenesis
-    - objenesis-2.6.jar
-  * Okio
-    - okio-1.13.0.jar
-  * Presto
-    - presto-array-0.206.jar
-    - presto-cli-0.206.jar
-    - presto-client-0.206.jar
-    - presto-geospatial-toolkit-0.206.jar
-    - presto-main-0.206.jar
-    - presto-matching-0.206.jar
-    - presto-memory-context-0.206.jar
-    - presto-parser-0.206.jar
-    - presto-spi-0.206.jar
-  * RocksDB JNI
-    - rocksdbjni-5.13.3.jar
-  * SnakeYAML
-    - snakeyaml-1.17.jar
-  * Snappy Java
-    - snappy-java-1.1.1.3.jar
-  * Bean Validation API
-    - validation-api-1.1.0.Final.jar
-  * Objectsize
-    - objectsize-0.0.12.jar
-  * Dropwizard Metrics
-    - metrics-core-3.1.0.jar
-    - metrics-graphite-3.1.0.jar
-    - metrics-jvm-3.1.0.jar
-  * Prometheus
-    - simpleclient-0.5.0.jar
-    - simpleclient_common-0.5.0.jar
-    - simpleclient_hotspot-0.5.0.jar
-    - simpleclient_servlet-0.5.0.jar
-  * LZ4
-    - lz4-java-1.5.0.jar
-  * JCTools
-    - jctools-core-2.1.2.jar
-  * Asynchronous Http Client
-    - async-http-client-2.7.0.jar
-    - async-http-client-netty-utils-2.7.0.jar
-  * Apache Bookkeeper
-    - bookkeeper-common-4.10.0.jar
-    - bookkeeper-common-allocator-4.10.0.jar
-    - bookkeeper-proto-4.10.0.jar
-    - bookkeeper-server-4.10.0.jar
-    - bookkeeper-stats-api-4.10.0.jar
-    - bookkeeper-tools-framework-4.10.0.jar
-    - circe-checksum-4.10.0.jar
-    - codahale-metrics-provider-4.10.0.jar
-    - cpu-affinity-4.10.0.jar
-    - http-server-4.10.0.jar
-    - prometheus-metrics-provider-4.10.0.jar
-  * Apache Commons
-    - commons-cli-1.2.jar
-    - commons-codec-1.10.jar
-    - commons-collections4-4.1.jar
-    - commons-configuration-1.10.jar
-    - commons-io-2.5.jar
-    - commons-lang-2.6.jar
-    - commons-logging-1.1.1.jar
-  * GSON
-    - gson-2.8.2.jar
-  * Jackson
-    - jackson-jaxrs-base-2.8.11.jar
-    - jackson-jaxrs-json-provider-2.8.11.jar
-    - jackson-module-jaxb-annotations-2.8.11.jar
-    - jackson-module-jsonSchema-2.8.11.jar
-  * Java Assist
-    - javassist-3.25.0-GA.jar
-  * Jetty
-    - jetty-http-9.4.20.v20190813.jar
-    - jetty-io-9.4.20.v20190813.jar
-    - jetty-security-9.4.20.v20190813.jar
-    - jetty-server-9.4.20.v20190813.jar
-    - jetty-servlet-9.4.20.v20190813.jar
-    - jetty-util-9.4.20.v20190813.jar
-  * Java Native Access
-    - jna-4.2.0.jar
-  * Yahoo Datasketches
-    - memory-0.8.3.jar
-    - sketches-core-0.8.3.jar
-  * Apache Zookeeper
-    - zookeeper-3.5.7.jar
-    - zookeeper-jute-3.5.7.jar
-  * Apache Yetus Audience Annotations
-    - audience-annotations-0.5.0.jar
-  * Swagger
-    - swagger-annotations-1.5.21.jar
-
-Protocol Buffers License
- * Protocol Buffers
-   - protobuf-shaded-2.1.0-incubating.jar
-   - protobuf-java-3.5.1.jar
-   - protobuf-java-util-3.5.1.jar
-
-BSD 3-clause "New" or "Revised" License
-  *  RE2J TD -- re2j-td-1.4.jar
-  *  DSL Platform JSON
-    - dsl-json-1.8.4.jar
-
-BSD License
- * ANTLR 4 Runtime -- antlr4-runtime-4.6.jar
- * ASM, a very small and fast Java bytecode manipulation framework
-    - asm-6.1.1.jar
-    - asm-analysis-6.0.jar
-    - asm-tree-6.0.jar
-    - asm-util-6.0.jar
- * JLine
-   - jline-2.14.6.jar
- * Zstd-jni
-   - zstd-jni-1.3.7-3.jar
-
-MIT License
- * Animal Sniffer Annotations
-   - animal-sniffer-annotations-1.14.jar
- * PCollections
-   - pcollections-2.1.2.jar
- * SLF4J
-   - slf4j-jdk14-1.7.25.jar
-   - slf4j-api-1.7.12.jar
-   - slf4j-api-1.7.25.jar
- * JCL 1.2 Implemented Over SLF4J
-   - jcl-over-slf4j-1.7.25.jar
- * JUL to SLF4J Bridge
-   - jul-to-slf4j-1.7.25.jar
- * Checker Qual
-   - checker-qual-2.0.0.jar
-
-CDDL - 1.0
- * OSGi Resource Locator
-    - osgi-resource-locator-1.0.1.jar
-
-CDDL-1.1 -- licenses/LICENSE-CDDL-1.1.txt
- * Java Annotations API
-   - javax.annotation-api-1.2.jar
-   - javax.annotation-api-1.3.1.jar
-   - javax.activation-1.2.0.jar
- * HK2 - Dependency Injection Kernel
-   - hk2-api-2.5.0-b42.jar
-   - hk2-locator-2.5.0-b42.jar
-   - hk2-utils-2.5.0-b42.jar
- * Jersey
-    - jaxrs-0.171.jar
-    - jersey-client-2.26.jar
-    - jersey-container-servlet-2.26.jar
-    - jersey-container-servlet-core-2.26.jar
-    - jersey-hk2-2.26.jar
-    - jersey-media-jaxb-2.26.jar
-    - jersey-server-2.26.jar
-    - jersey-common-2.26.jar
- * JAXB
-    - jaxb-api-2.2.6.jar
-    - jaxb-api-2.3.1.jar
-    - jaxb-impl-2.2.6.jar
-
- Eclipse Public License 1.0 -- licenses/LICENSE-AspectJ.txt
-  * Aether
-     - aether-api-1.13.1.jar
-     - aether-connector-asynchttpclient-1.13.1.jar
-     - aether-connector-file-1.13.1.jar
-     - aether-impl-1.13.1.jar
-     - aether-spi-1.13.1.jar
-     - aether-util-1.13.1.jar
-  * JTS Core
-     - jts-core-1.15.0.jar
-  *JGraphT Core
-     - jgrapht-core-0.9.0.jar
-  * Logback Core Module
-    - logback-core-1.2.3.jar
-  * MIME Streaming Extension
-    - mimepull-1.9.6.jar
-
-Public Domain (CC0) -- licenses/LICENSE-CC0.txt
- * HdrHistogram
-   - HdrHistogram-2.1.9.jar
- * AOP Alliance
-   - aopalliance-1.0.jar
- * Reactive Streams
-    - reactive-streams-1.0.2.jar
-
 Bouncy Castle License
  * Bouncy Castle -- licenses/LICENSE-bouncycastle.txt
-    - bcpkix-jdk15on-1.60.jar
-    - bcprov-jdk15on-1.60.jar
-
-Creative Commons Attribution License
- * Jcip -- licenses/LICENSE-jcip.txt
-    - jcip-annotations-1.0.jar
+    - org.bouncycastle-bcpkix-jdk15on-1.60.jar
+    - org.bouncycastle-bcprov-jdk15on-1.60.jar
+    - org.bouncycastle-bcprov-ext-jdk15on-1.60.jar
diff --git a/bouncy-castle/bc/pom.xml b/bouncy-castle/bc/pom.xml
new file mode 100644
index 0000000..ce86a1e
--- /dev/null
+++ b/bouncy-castle/bc/pom.xml
@@ -0,0 +1,64 @@
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.pulsar</groupId>
+    <artifactId>bouncy-castle-parent</artifactId>
+    <version>2.6.0-SNAPSHOT</version>
+    <relativePath>..</relativePath>
+  </parent>
+
+  <artifactId>bouncy-castle-bc</artifactId>
+  <name>Apache Pulsar :: Bouncy Castle :: BC</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>pulsar-common</artifactId>
+      <version>${project.parent.version}</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bcpkix-jdk15on</artifactId>
+      <version>${bouncycastle.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bcprov-ext-jdk15on</artifactId>
+      <version>${bouncycastle.version}</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.nifi</groupId>
+        <artifactId>nifi-nar-maven-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/bouncy-castle/bc/src/main/java/org/apache/pulsar/bcloader/BouncyCastleLoader.java b/bouncy-castle/bc/src/main/java/org/apache/pulsar/bcloader/BouncyCastleLoader.java
new file mode 100644
index 0000000..6e43e9e
--- /dev/null
+++ b/bouncy-castle/bc/src/main/java/org/apache/pulsar/bcloader/BouncyCastleLoader.java
@@ -0,0 +1,47 @@
+/**
+ * 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.bcloader;
+
+import static org.apache.pulsar.common.util.SecurityUtility.BC;
+
+import java.security.Provider;
+import java.security.Security;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.pulsar.common.util.BCLoader;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+
+/**
+ * This is a Bouncy Castle provider Loader.
+ */
+@Slf4j
+public class BouncyCastleLoader implements BCLoader {
+    public static Provider provider;
+    static {
+        if (Security.getProvider(BC) == null) {
+            Security.addProvider(new BouncyCastleProvider());
+        }
+        provider = Security.getProvider(BC);
+        log.info("BouncyCastle Provider BC: {}", provider);
+    }
+
+    @Override
+    public Provider getProvider() {
+        return Security.getProvider(BC);
+    }
+}
diff --git a/bouncy-castle/bc/src/main/resources/META-INF/services/bouncy-castle.yaml b/bouncy-castle/bc/src/main/resources/META-INF/services/bouncy-castle.yaml
new file mode 100644
index 0000000..5f8217c
--- /dev/null
+++ b/bouncy-castle/bc/src/main/resources/META-INF/services/bouncy-castle.yaml
@@ -0,0 +1,22 @@
+#
+# 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.
+#
+
+name: bouncy-castle
+description: loader for Bouncy Castle provider
+bcLoaderClass: org.apache.pulsar.bcloader.BouncyCastleLoader
diff --git a/bouncy-castle/bcfips-include-test/pom.xml b/bouncy-castle/bcfips-include-test/pom.xml
new file mode 100644
index 0000000..e15967d
--- /dev/null
+++ b/bouncy-castle/bcfips-include-test/pom.xml
@@ -0,0 +1,95 @@
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.pulsar</groupId>
+    <artifactId>bouncy-castle-parent</artifactId>
+    <version>2.6.0-SNAPSHOT</version>
+    <relativePath>..</relativePath>
+  </parent>
+
+  <artifactId>bcfips-include-test</artifactId>
+  <name>Pulsar Bouncy Castle FIPS Test</name>
+  <description> Broker and client runs auth include BC FIPS verison</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.pulsar</groupId>
+      <artifactId>testmocks</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>pulsar-broker</artifactId>
+      <version>${project.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>${project.groupId}</groupId>
+          <artifactId>bouncy-castle-bc-shaded</artifactId>
+        </exclusion>
+      </exclusions>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>pulsar-broker</artifactId>
+      <version>${project.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>${project.groupId}</groupId>
+          <artifactId>bouncy-castle-bc-shaded</artifactId>
+        </exclusion>
+      </exclusions>
+      <scope>test</scope>
+    </dependency>
+
+    <!--exclude bouncy castle, then load fips version-->
+    <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bc-fips</artifactId>
+      <version>${bouncycastlefips.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bcpkix-fips</artifactId>
+      <version>${bouncycastlefips.version}</version>
+    </dependency>
+
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-deploy-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/bouncy-castle/bcfips-include-test/src/test/java/org/apache/pulsar/client/TlsProducerConsumerBase.java b/bouncy-castle/bcfips-include-test/src/test/java/org/apache/pulsar/client/TlsProducerConsumerBase.java
new file mode 100644
index 0000000..000f96c
--- /dev/null
+++ b/bouncy-castle/bcfips-include-test/src/test/java/org/apache/pulsar/client/TlsProducerConsumerBase.java
@@ -0,0 +1,111 @@
+/**
+ * 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.client;
+
+import static org.mockito.Mockito.spy;
+
+import com.google.common.collect.Sets;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import org.apache.pulsar.client.admin.PulsarAdmin;
+import org.apache.pulsar.client.api.ClientBuilder;
+import org.apache.pulsar.client.api.ProducerConsumerBase;
+import org.apache.pulsar.client.api.PulsarClient;
+import org.apache.pulsar.client.impl.auth.AuthenticationTls;
+import org.apache.pulsar.common.policies.data.ClusterData;
+import org.apache.pulsar.common.policies.data.TenantInfo;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+
+public class TlsProducerConsumerBase extends ProducerConsumerBase {
+    protected final String TLS_TRUST_CERT_FILE_PATH = "./src/test/resources/authentication/tls/cacert.pem";
+    protected final String TLS_CLIENT_CERT_FILE_PATH = "./src/test/resources/authentication/tls/client-cert.pem";
+    protected final String TLS_CLIENT_KEY_FILE_PATH = "./src/test/resources/authentication/tls/client-key.pem";
+    protected final String TLS_SERVER_CERT_FILE_PATH = "./src/test/resources/authentication/tls/broker-cert.pem";
+    protected final String TLS_SERVER_KEY_FILE_PATH = "./src/test/resources/authentication/tls/broker-key.pem";
+    private final String clusterName = "use";
+
+    @BeforeMethod
+    @Override
+    protected void setup() throws Exception {
+        // TLS configuration for Broker
+        internalSetUpForBroker();
+
+        // Start Broker
+        super.init();
+    }
+
+    @AfterMethod
+    @Override
+    protected void cleanup() throws Exception {
+        super.internalCleanup();
+    }
+
+    protected void internalSetUpForBroker() throws Exception {
+        conf.setBrokerServicePortTls(Optional.of(0));
+        conf.setWebServicePortTls(Optional.of(0));
+        conf.setTlsCertificateFilePath(TLS_SERVER_CERT_FILE_PATH);
+        conf.setTlsKeyFilePath(TLS_SERVER_KEY_FILE_PATH);
+        conf.setTlsTrustCertsFilePath(TLS_TRUST_CERT_FILE_PATH);
+        conf.setClusterName(clusterName);
+        conf.setTlsRequireTrustedClientCertOnConnect(true);
+        Set<String> tlsProtocols = Sets.newConcurrentHashSet();
+        tlsProtocols.add("TLSv1.2");
+        conf.setTlsProtocols(tlsProtocols);
+    }
+
+    protected void internalSetUpForClient(boolean addCertificates, String lookupUrl) throws Exception {
+        if (pulsarClient != null) {
+            pulsarClient.close();
+        }
+
+        ClientBuilder clientBuilder = PulsarClient.builder().serviceUrl(lookupUrl)
+                .tlsTrustCertsFilePath(TLS_TRUST_CERT_FILE_PATH).enableTls(true).allowTlsInsecureConnection(false)
+                .operationTimeout(1000, TimeUnit.MILLISECONDS);
+        if (addCertificates) {
+            Map<String, String> authParams = new HashMap<>();
+            authParams.put("tlsCertFile", TLS_CLIENT_CERT_FILE_PATH);
+            authParams.put("tlsKeyFile", TLS_CLIENT_KEY_FILE_PATH);
+            clientBuilder.authentication(AuthenticationTls.class.getName(), authParams);
+        }
+        pulsarClient = clientBuilder.build();
+    }
+
+    protected void internalSetUpForNamespace() throws Exception {
+        Map<String, String> authParams = new HashMap<>();
+        authParams.put("tlsCertFile", TLS_CLIENT_CERT_FILE_PATH);
+        authParams.put("tlsKeyFile", TLS_CLIENT_KEY_FILE_PATH);
+
+        if (admin != null) {
+            admin.close();
+        }
+
+        admin = spy(PulsarAdmin.builder().serviceHttpUrl(brokerUrlTls.toString())
+                .tlsTrustCertsFilePath(TLS_TRUST_CERT_FILE_PATH).allowTlsInsecureConnection(false)
+                .authentication(AuthenticationTls.class.getName(), authParams).build());
+        admin.clusters().createCluster(clusterName, new ClusterData(brokerUrl.toString(), brokerUrlTls.toString(),
+                pulsar.getBrokerServiceUrl(), pulsar.getBrokerServiceUrlTls()));
+        admin.tenants().createTenant("my-property",
+                new TenantInfo(Sets.newHashSet("appid1", "appid2"), Sets.newHashSet("use")));
+        admin.namespaces().createNamespace("my-property/my-ns");
+    }
+}
diff --git a/bouncy-castle/bcfips-include-test/src/test/java/org/apache/pulsar/client/TlsProducerConsumerTest.java b/bouncy-castle/bcfips-include-test/src/test/java/org/apache/pulsar/client/TlsProducerConsumerTest.java
new file mode 100644
index 0000000..85ee130
--- /dev/null
+++ b/bouncy-castle/bcfips-include-test/src/test/java/org/apache/pulsar/client/TlsProducerConsumerTest.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.client;
+
+import java.util.Arrays;
+import java.util.concurrent.TimeUnit;
+import org.apache.pulsar.client.api.Consumer;
+import org.apache.pulsar.client.api.Message;
+import org.apache.pulsar.client.api.Producer;
+import org.apache.pulsar.client.api.SubscriptionType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class TlsProducerConsumerTest extends TlsProducerConsumerBase {
+    private static final Logger log = LoggerFactory.getLogger(TlsProducerConsumerTest.class);
+
+    /**
+     * verifies that messages whose size is larger than 2^14 bytes (max size of single TLS chunk) can be
+     * produced/consumed
+     *
+     * @throws Exception
+     */
+    @Test(timeOut = 30000)
+    public void testTlsLargeSizeMessage() throws Exception {
+        log.info("-- Starting {} test --", methodName);
+
+        final int MESSAGE_SIZE = 16 * 1024 + 1;
+        log.info("-- message size --", MESSAGE_SIZE);
+
+        internalSetUpForClient(true, pulsar.getBrokerServiceUrlTls());
+        internalSetUpForNamespace();
+
+        Consumer<byte[]> consumer = pulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic1")
+                .subscriptionName("my-subscriber-name").subscribe();
+
+        Producer<byte[]> producer = pulsarClient.newProducer().topic("persistent://my-property/use/my-ns/my-topic1")
+                .create();
+        for (int i = 0; i < 10; i++) {
+            byte[] message = new byte[MESSAGE_SIZE];
+            Arrays.fill(message, (byte) i);
+            producer.send(message);
+        }
+
+        Message<byte[]> msg = null;
+        for (int i = 0; i < 10; i++) {
+            msg = consumer.receive(5, TimeUnit.SECONDS);
+            byte[] expected = new byte[MESSAGE_SIZE];
+            Arrays.fill(expected, (byte) i);
+            Assert.assertEquals(expected, msg.getData());
+        }
+        // Acknowledge the consumption of all messages at once
+        consumer.acknowledgeCumulative(msg);
+        consumer.close();
+        log.info("-- Exiting {} test --", methodName);
+    }
+
+    @Test(timeOut = 30000)
+    public void testTlsClientAuthOverBinaryProtocol() throws Exception {
+        log.info("-- Starting {} test --", methodName);
+
+        final int MESSAGE_SIZE = 16 * 1024 + 1;
+        log.info("-- message size --", MESSAGE_SIZE);
+        internalSetUpForNamespace();
+
+        // Test 1 - Using TLS on binary protocol without sending certs - expect failure
+        internalSetUpForClient(false, pulsar.getBrokerServiceUrlTls());
+        try {
+            pulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic1")
+                    .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Exclusive).subscribe();
+            Assert.fail("Server should have failed the TLS handshake since client didn't .");
+        } catch (Exception ex) {
+            // OK
+        }
+
+        // Test 2 - Using TLS on binary protocol - sending certs
+        internalSetUpForClient(true, pulsar.getBrokerServiceUrlTls());
+        try {
+            pulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic1")
+                    .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Exclusive).subscribe();
+        } catch (Exception ex) {
+            Assert.fail("Should not fail since certs are sent.");
+        }
+    }
+
+    @Test(timeOut = 30000)
+    public void testTlsClientAuthOverHTTPProtocol() throws Exception {
+        log.info("-- Starting {} test --", methodName);
+
+        final int MESSAGE_SIZE = 16 * 1024 + 1;
+        log.info("-- message size --", MESSAGE_SIZE);
+        internalSetUpForNamespace();
+
+        // Test 1 - Using TLS on https without sending certs - expect failure
+        internalSetUpForClient(false, pulsar.getWebServiceAddressTls());
+        try {
+            pulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic1")
+                    .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Exclusive).subscribe();
+            Assert.fail("Server should have failed the TLS handshake since client didn't .");
+        } catch (Exception ex) {
+            // OK
+        }
+
+        // Test 2 - Using TLS on https - sending certs
+        internalSetUpForClient(true, pulsar.getWebServiceAddressTls());
+        try {
+            pulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic1")
+                    .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Exclusive).subscribe();
+        } catch (Exception ex) {
+            Assert.fail("Should not fail since certs are sent.");
+        }
+    }
+}
diff --git a/bouncy-castle/bcfips-include-test/src/test/resources/authentication/tls/broker-cert.pem b/bouncy-castle/bcfips-include-test/src/test/resources/authentication/tls/broker-cert.pem
new file mode 100644
index 0000000..69ad71c
--- /dev/null
+++ b/bouncy-castle/bcfips-include-test/src/test/resources/authentication/tls/broker-cert.pem
@@ -0,0 +1,73 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            88:08:98:b3:13:d8:00:97
+        Signature Algorithm: sha1WithRSAEncryption
+        Issuer: C=US, ST=CA, O=Apache, OU=Pulsar Incubator, CN=localhost
+        Validity
+            Not Before: Feb 17 02:06:21 2018 GMT
+            Not After : Nov 16 00:00:00 2030 GMT
+        Subject: C=US, ST=CA, O=Apache, OU=Apache Pulsar, CN=localhost
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (2048 bit)
+                Modulus (2048 bit):
+                    00:af:bf:b7:2d:98:ad:9d:f6:da:a3:13:d4:62:0f:
+                    98:be:1c:a2:89:22:ba:6f:d5:fd:1f:67:e3:91:03:
+                    98:80:81:0e:ed:d8:f6:70:7f:2c:36:68:3d:53:ea:
+                    58:3a:a6:d5:89:66:4b:bd:1e:57:71:13:6d:4b:11:
+                    e5:40:a5:76:84:24:92:40:58:80:96:c9:1f:2c:c4:
+                    55:eb:a3:79:73:70:5c:37:9a:89:ed:2f:ba:6b:e3:
+                    82:7c:69:4a:02:54:8b:81:5e:3c:bf:4c:8a:cb:ea:
+                    2c:5e:83:e7:b7:10:08:5f:82:58:a3:89:d1:da:92:
+                    ba:2a:28:ee:30:28:3f:5b:ae:10:71:96:c7:e1:12:
+                    c5:b0:1a:ad:44:6f:44:3a:11:4a:9a:3c:0f:8d:06:
+                    80:7b:34:ef:3f:6c:f4:5e:c5:44:54:1e:c8:dd:c7:
+                    80:85:80:d9:68:e6:c6:53:03:77:e1:fe:18:61:07:
+                    77:05:4c:ed:59:bc:5d:41:38:6a:ef:5d:a1:b2:60:
+                    98:d4:48:28:95:02:8a:0e:fd:cf:7b:1b:d2:11:cc:
+                    10:0c:50:73:d7:cc:38:6c:83:dd:79:26:aa:90:c8:
+                    9b:84:86:bc:59:e9:62:69:f4:98:1b:c4:80:78:7e:
+                    a0:1a:81:9d:d2:e1:66:dd:c4:cc:fc:63:04:ac:ec:
+                    a7:35
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                D3:F3:19:AE:74:B1:AF:E7:AF:08:7B:16:72:78:29:87:79:ED:30:8C
+            X509v3 Authority Key Identifier: 
+                keyid:D4:7A:CD:0F:44:1B:16:29:25:14:ED:A2:EF:13:0F:A7:46:09:78:F6
+
+    Signature Algorithm: sha1WithRSAEncryption
+        0f:04:f3:91:f2:87:19:fe:9d:f8:34:5a:24:4a:00:d1:58:bf:
+        1e:b2:77:67:07:bc:78:b5:4b:9a:4b:fd:a1:e5:dc:0e:09:84:
+        9e:59:c4:dd:cf:f7:2e:bf:da:f3:31:36:6b:81:6e:a2:88:76:
+        e4:2e:0b:36:44:82:36:8f:80:93:f4:9e:fc:ed:85:d0:97:da:
+        0f:fb:c9:b9:8b:da:ae:07:3d:4f:82:b7:0c:25:22:63:12:6b:
+        0a:e9:c4:12:a4:5c:ed:11:12:cc:fe:b0:2e:d4:c1:ec:79:01:
+        60:ea:cc:cc:e5:66:cc:57:f6:55:a9:09:4c:63:01:e9:b4:2e:
+        73:a5
+-----BEGIN CERTIFICATE-----
+MIIDLjCCApegAwIBAgIJAIgImLMT2ACXMA0GCSqGSIb3DQEBBQUAMFoxCzAJBgNV
+BAYTAlVTMQswCQYDVQQIEwJDQTEPMA0GA1UEChMGQXBhY2hlMRkwFwYDVQQLExBQ
+dWxzYXIgSW5jdWJhdG9yMRIwEAYDVQQDEwlsb2NhbGhvc3QwHhcNMTgwMjE3MDIw
+NjIxWhcNMzAxMTE2MDAwMDAwWjBXMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex
+DzANBgNVBAoTBkFwYWNoZTEWMBQGA1UECxMNQXBhY2hlIFB1bHNhcjESMBAGA1UE
+AxMJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr7+3
+LZitnfbaoxPUYg+YvhyiiSK6b9X9H2fjkQOYgIEO7dj2cH8sNmg9U+pYOqbViWZL
+vR5XcRNtSxHlQKV2hCSSQFiAlskfLMRV66N5c3BcN5qJ7S+6a+OCfGlKAlSLgV48
+v0yKy+osXoPntxAIX4JYo4nR2pK6KijuMCg/W64QcZbH4RLFsBqtRG9EOhFKmjwP
+jQaAezTvP2z0XsVEVB7I3ceAhYDZaObGUwN34f4YYQd3BUztWbxdQThq712hsmCY
+1EgolQKKDv3PexvSEcwQDFBz18w4bIPdeSaqkMibhIa8WeliafSYG8SAeH6gGoGd
+0uFm3cTM/GMErOynNQIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQf
+Fh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU0/MZrnSx
+r+evCHsWcngph3ntMIwwHwYDVR0jBBgwFoAU1HrND0QbFiklFO2i7xMPp0YJePYw
+DQYJKoZIhvcNAQEFBQADgYEADwTzkfKHGf6d+DRaJEoA0Vi/HrJ3Zwe8eLVLmkv9
+oeXcDgmEnlnE3c/3Lr/a8zE2a4Fuooh25C4LNkSCNo+Ak/Se/O2F0JfaD/vJuYva
+rgc9T4K3DCUiYxJrCunEEqRc7RESzP6wLtTB7HkBYOrMzOVmzFf2VakJTGMB6bQu
+c6U=
+-----END CERTIFICATE-----
diff --git a/bouncy-castle/bcfips-include-test/src/test/resources/authentication/tls/broker-key.pem b/bouncy-castle/bcfips-include-test/src/test/resources/authentication/tls/broker-key.pem
new file mode 100644
index 0000000..004bf8e
--- /dev/null
+++ b/bouncy-castle/bcfips-include-test/src/test/resources/authentication/tls/broker-key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCvv7ctmK2d9tqj
+E9RiD5i+HKKJIrpv1f0fZ+ORA5iAgQ7t2PZwfyw2aD1T6lg6ptWJZku9HldxE21L
+EeVApXaEJJJAWICWyR8sxFXro3lzcFw3montL7pr44J8aUoCVIuBXjy/TIrL6ixe
+g+e3EAhfglijidHakroqKO4wKD9brhBxlsfhEsWwGq1Eb0Q6EUqaPA+NBoB7NO8/
+bPRexURUHsjdx4CFgNlo5sZTA3fh/hhhB3cFTO1ZvF1BOGrvXaGyYJjUSCiVAooO
+/c97G9IRzBAMUHPXzDhsg915JqqQyJuEhrxZ6WJp9JgbxIB4fqAagZ3S4WbdxMz8
+YwSs7Kc1AgMBAAECggEAAaWEK9MwXTiA1+JJrRmETtOp2isPIBkbI/4vLZ6hASM0
+ZpoPxQIMAf58BJs/dF03xu/EaeMs4oxSC9ABG9fxAk/tZtjta3w65Ip6W5jOfHxj
+AMpb3HMEBhq9kDjUTq1IGVAutYQcEMkC3WfS9e4ahfqMpguWgbu6LsbvZFgcL9mv
+pGnKv9YVe6Xk6isvqtq6G1af0rd7c//xF0i0e/qEo83Buok3gLEZOELZbcRxjUYc
+jnyglnXnwkGjuL4E3wgS3l73ZKsb6+AYoqhMPVz8t4/PN3tTrsBJKOSYo8KzIm0U
+ek9T8XmPbP0cuheRxp9Dp8TXJJQZK0N9jz+EL0ogQQKBgQDnavm8GpR4pap9cDOc
++YI5s823b507pNdSU8elO9gLsP0JlFzv+sqghVko29r85D7Vn3MkgYTy0S4ANLCs
+0NFDY8N2QH6U1dTkk1QXZydVZDuKJ5SSpC4v+Vafl8yDxhB4Nlxhbm9vJEMfLcXh
+2kL6UlAuFDtYD0AdczwnHu5DjQKBgQDCauocm55FpcyDMMBO2CjurxcjBYS3S1xT
+Bz+sPtxJLjlKbAt8kSHUQcCcX9zhrQBfsT38LATCmKaOFqUW5/PPh2LcrxiMqlL1
+OJBUJ3Te2LTjlUn8r+DHv/69UIh5tchwRr3YgB0DuIs7jfmr4VfiOWTBtPVhoGFR
+1Wt60j30SQKBgHzreS26J2VNAFBALgxRf6OIVMbtgDG/FOCDCyU9vazp+F2gcd61
+QYYPFYcBzx9uUiDctroBFHRCyJMh3jEbc6ruAogl3m6XUxmkEeOkMk5dEerM3N2f
+tLL+5Gy385U6aI+LwKhzhcG4EGeXPNdjC362ykNldnddnB2Jo/H2N2XNAoGAdnft
+xpbxP+GDGKIZXTIM5zzcLWQMdiC+1n1BSHVZiGJZWMczzKknYw7aDq+/iekApE79
+xW8RS373ZvfXi3i2Mcx+6pjrrbOQL4tTL2SHq8+DknaDCi4mG7IbyUKMlxW1WO1S
+e929UGogtZ6S+DCte9WbVwosyFuRUetpvgLk67kCgYBWetihZjgBWrqVYT24TTRH
+KxzSzH1JgzzF9qgTdlhXDv9hC+Kc0uTKsgViesDqVuCOjkwzY5OQr9c6duO0fwwP
+qNk/qltdgjMC5iiv7duyukfbEuqKEdGGer9HFb7en96dZdVQJpYHaaslAGurtD80
+ejCQZgzR2XaHSuIQb0IUVQ==
+-----END PRIVATE KEY-----
diff --git a/bouncy-castle/bcfips-include-test/src/test/resources/authentication/tls/cacert.pem b/bouncy-castle/bcfips-include-test/src/test/resources/authentication/tls/cacert.pem
new file mode 100644
index 0000000..55e9067
--- /dev/null
+++ b/bouncy-castle/bcfips-include-test/src/test/resources/authentication/tls/cacert.pem
@@ -0,0 +1,62 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            88:08:98:b3:13:d8:00:94
+        Signature Algorithm: sha1WithRSAEncryption
+        Issuer: C=US, ST=CA, O=Apache, OU=Pulsar Incubator, CN=localhost
+        Validity
+            Not Before: Feb 17 01:37:33 2018 GMT
+            Not After : Feb 16 01:37:33 2021 GMT
+        Subject: C=US, ST=CA, O=Apache, OU=Pulsar Incubator, CN=localhost
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:ea:16:8d:a5:b1:19:61:34:54:07:02:60:4e:6d:
+                    54:92:08:fd:fb:23:79:9c:05:bf:14:f7:bc:aa:db:
+                    2b:42:a4:35:74:86:e3:00:ad:8b:18:79:73:7d:f2:
+                    d1:74:dd:74:bc:b8:a2:4c:80:c9:f3:80:ce:bf:f8:
+                    6d:97:f5:05:4f:f4:b2:99:50:e8:d8:b0:c4:57:a0:
+                    e7:dc:82:57:75:2a:a2:02:21:76:f7:37:c2:dc:7c:
+                    4c:36:a6:73:6f:dc:75:48:72:ad:fa:98:02:70:b2:
+                    5e:a2:83:cc:c3:8d:20:a7:1e:bc:d7:1e:c1:d1:7e:
+                    39:35:4b:f5:be:6b:c1:0f:f9
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                D4:7A:CD:0F:44:1B:16:29:25:14:ED:A2:EF:13:0F:A7:46:09:78:F6
+            X509v3 Authority Key Identifier: 
+                keyid:D4:7A:CD:0F:44:1B:16:29:25:14:ED:A2:EF:13:0F:A7:46:09:78:F6
+                DirName:/C=US/ST=CA/O=Apache/OU=Pulsar Incubator/CN=localhost
+                serial:88:08:98:B3:13:D8:00:94
+
+            X509v3 Basic Constraints: 
+                CA:TRUE
+    Signature Algorithm: sha1WithRSAEncryption
+        5e:30:c5:7b:30:3e:1e:16:cd:ba:66:f1:2a:19:13:8a:1a:00:
+        08:f4:1e:8c:e4:3d:57:13:65:96:bf:07:58:55:52:37:3e:aa:
+        2c:19:de:ee:c3:92:6e:79:f3:06:0e:9a:7b:e0:02:50:c3:ef:
+        3b:84:ea:8f:e0:f0:16:a6:a6:67:8b:be:73:0e:5d:f7:88:39:
+        d3:d4:df:85:ad:7c:c1:4f:fa:55:55:6f:c2:48:4e:8e:82:fa:
+        72:3b:8e:9d:dc:f7:2e:9d:47:8e:e5:c9:a2:ee:b1:76:94:15:
+        7c:7a:62:bc:06:45:fa:61:2e:33:8c:18:3e:e9:d5:90:a5:a6:
+        80:5a
+-----BEGIN CERTIFICATE-----
+MIIC8jCCAlugAwIBAgIJAIgImLMT2ACUMA0GCSqGSIb3DQEBBQUAMFoxCzAJBgNV
+BAYTAlVTMQswCQYDVQQIEwJDQTEPMA0GA1UEChMGQXBhY2hlMRkwFwYDVQQLExBQ
+dWxzYXIgSW5jdWJhdG9yMRIwEAYDVQQDEwlsb2NhbGhvc3QwHhcNMTgwMjE3MDEz
+NzMzWhcNMjEwMjE2MDEzNzMzWjBaMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex
+DzANBgNVBAoTBkFwYWNoZTEZMBcGA1UECxMQUHVsc2FyIEluY3ViYXRvcjESMBAG
+A1UEAxMJbG9jYWxob3N0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDqFo2l
+sRlhNFQHAmBObVSSCP37I3mcBb8U97yq2ytCpDV0huMArYsYeXN98tF03XS8uKJM
+gMnzgM6/+G2X9QVP9LKZUOjYsMRXoOfcgld1KqICIXb3N8LcfEw2pnNv3HVIcq36
+mAJwsl6ig8zDjSCnHrzXHsHRfjk1S/W+a8EP+QIDAQABo4G/MIG8MB0GA1UdDgQW
+BBTUes0PRBsWKSUU7aLvEw+nRgl49jCBjAYDVR0jBIGEMIGBgBTUes0PRBsWKSUU
+7aLvEw+nRgl49qFepFwwWjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMQ8wDQYD
+VQQKEwZBcGFjaGUxGTAXBgNVBAsTEFB1bHNhciBJbmN1YmF0b3IxEjAQBgNVBAMT
+CWxvY2FsaG9zdIIJAIgImLMT2ACUMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEF
+BQADgYEAXjDFezA+HhbNumbxKhkTihoACPQejOQ9VxNllr8HWFVSNz6qLBne7sOS
+bnnzBg6ae+ACUMPvO4Tqj+DwFqamZ4u+cw5d94g509Tfha18wU/6VVVvwkhOjoL6
+cjuOndz3Lp1HjuXJou6xdpQVfHpivAZF+mEuM4wYPunVkKWmgFo=
+-----END CERTIFICATE-----
diff --git a/bouncy-castle/bcfips-include-test/src/test/resources/authentication/tls/client-cert.pem b/bouncy-castle/bcfips-include-test/src/test/resources/authentication/tls/client-cert.pem
new file mode 100644
index 0000000..61847f2
--- /dev/null
+++ b/bouncy-castle/bcfips-include-test/src/test/resources/authentication/tls/client-cert.pem
@@ -0,0 +1,73 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            88:08:98:b3:13:d8:00:99
+        Signature Algorithm: sha1WithRSAEncryption
+        Issuer: C=US, ST=CA, O=Apache, OU=Pulsar Incubator, CN=localhost
+        Validity
+            Not Before: Feb 17 02:50:05 2018 GMT
+            Not After : Nov 16 00:00:00 2030 GMT
+        Subject: C=US, ST=CA, O=Apache, OU=Apache Pulsar, CN=superUser
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (2048 bit)
+                Modulus (2048 bit):
+                    00:cd:43:7d:98:40:f9:b0:5b:bc:ae:db:c0:0b:ad:
+                    26:90:96:e0:62:38:ed:68:b1:70:46:3b:de:44:f9:
+                    14:51:86:10:eb:ca:90:e7:88:e8:f9:91:85:e0:dd:
+                    b5:b4:14:b9:78:e3:86:d5:54:6d:68:ec:14:92:b4:
+                    f8:22:5b:05:3d:ed:31:25:65:08:05:84:ca:e6:0c:
+                    21:12:58:32:c7:1a:60:a3:4f:d2:4a:9e:28:19:7c:
+                    45:84:00:8c:89:dc:de:8a:e5:4f:88:91:cc:a4:f1:
+                    81:45:4c:7d:c2:ff:e2:c1:89:c6:12:73:95:e2:36:
+                    bd:db:ae:8b:5a:68:6a:90:51:de:2b:88:5f:aa:67:
+                    f4:a8:e3:63:dc:be:19:82:cc:9d:7f:e6:8d:fb:82:
+                    be:22:01:3d:56:13:3b:5b:04:b4:e8:c5:18:e6:2e:
+                    0d:fa:ba:4a:8d:e8:c6:5a:a1:51:9a:4a:62:d7:af:
+                    dd:b4:fc:e2:d5:cd:ae:99:6c:5c:61:56:0b:d7:0c:
+                    1a:77:5c:f5:3a:6a:54:b5:9e:33:ac:a9:75:28:9a:
+                    76:af:d0:7a:57:00:1b:91:13:31:fd:42:88:21:47:
+                    05:10:01:2f:59:bb:c7:3a:d9:e1:58:4c:1b:6c:71:
+                    b6:98:ef:dd:03:82:58:a3:32:dc:90:a1:b6:a6:1e:
+                    e1:0b
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                53:7C:D5:D1:52:97:9A:D6:D5:EA:EC:B6:0C:9B:43:39:19:73:F6:2C
+            X509v3 Authority Key Identifier: 
+                keyid:D4:7A:CD:0F:44:1B:16:29:25:14:ED:A2:EF:13:0F:A7:46:09:78:F6
+
+    Signature Algorithm: sha1WithRSAEncryption
+        e4:03:82:ff:be:df:7c:73:2a:c5:8f:7d:87:ab:95:b1:2b:e5:
+        f7:41:22:4f:28:54:84:7a:cc:fe:70:89:0f:48:e5:8a:17:e1:
+        44:ad:12:e9:a1:3a:c7:84:55:f0:7c:29:52:0a:a1:ab:cc:5b:
+        31:e5:b2:37:73:3a:8d:f2:f1:fb:e8:f6:a2:b9:ef:11:10:f8:
+        31:43:8f:af:ce:09:f4:cb:96:0e:d4:58:42:6e:86:ab:b9:03:
+        19:8b:4a:6e:ef:50:c0:7e:c9:0b:1d:2b:42:bf:eb:d0:06:05:
+        84:ea:5a:8a:22:5c:56:fa:da:2a:9f:8a:b2:90:66:8c:5e:01:
+        87:45
+-----BEGIN CERTIFICATE-----
+MIIDLjCCApegAwIBAgIJAIgImLMT2ACZMA0GCSqGSIb3DQEBBQUAMFoxCzAJBgNV
+BAYTAlVTMQswCQYDVQQIEwJDQTEPMA0GA1UEChMGQXBhY2hlMRkwFwYDVQQLExBQ
+dWxzYXIgSW5jdWJhdG9yMRIwEAYDVQQDEwlsb2NhbGhvc3QwHhcNMTgwMjE3MDI1
+MDA1WhcNMzAxMTE2MDAwMDAwWjBXMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex
+DzANBgNVBAoTBkFwYWNoZTEWMBQGA1UECxMNQXBhY2hlIFB1bHNhcjESMBAGA1UE
+AxMJc3VwZXJVc2VyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzUN9
+mED5sFu8rtvAC60mkJbgYjjtaLFwRjveRPkUUYYQ68qQ54jo+ZGF4N21tBS5eOOG
+1VRtaOwUkrT4IlsFPe0xJWUIBYTK5gwhElgyxxpgo0/SSp4oGXxFhACMidzeiuVP
+iJHMpPGBRUx9wv/iwYnGEnOV4ja9266LWmhqkFHeK4hfqmf0qONj3L4Zgsydf+aN
++4K+IgE9VhM7WwS06MUY5i4N+rpKjejGWqFRmkpi16/dtPzi1c2umWxcYVYL1wwa
+d1z1OmpUtZ4zrKl1KJp2r9B6VwAbkRMx/UKIIUcFEAEvWbvHOtnhWEwbbHG2mO/d
+A4JYozLckKG2ph7hCwIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQf
+Fh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUU3zV0VKX
+mtbV6uy2DJtDORlz9iwwHwYDVR0jBBgwFoAU1HrND0QbFiklFO2i7xMPp0YJePYw
+DQYJKoZIhvcNAQEFBQADgYEA5AOC/77ffHMqxY99h6uVsSvl90EiTyhUhHrM/nCJ
+D0jlihfhRK0S6aE6x4RV8HwpUgqhq8xbMeWyN3M6jfLx++j2ornvERD4MUOPr84J
+9MuWDtRYQm6Gq7kDGYtKbu9QwH7JCx0rQr/r0AYFhOpaiiJcVvraKp+KspBmjF4B
+h0U=
+-----END CERTIFICATE-----
diff --git a/bouncy-castle/bcfips-include-test/src/test/resources/authentication/tls/client-key.pem b/bouncy-castle/bcfips-include-test/src/test/resources/authentication/tls/client-key.pem
new file mode 100644
index 0000000..3835b3e
--- /dev/null
+++ b/bouncy-castle/bcfips-include-test/src/test/resources/authentication/tls/client-key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDNQ32YQPmwW7yu
+28ALrSaQluBiOO1osXBGO95E+RRRhhDrypDniOj5kYXg3bW0FLl444bVVG1o7BSS
+tPgiWwU97TElZQgFhMrmDCESWDLHGmCjT9JKnigZfEWEAIyJ3N6K5U+Ikcyk8YFF
+TH3C/+LBicYSc5XiNr3brotaaGqQUd4riF+qZ/So42PcvhmCzJ1/5o37gr4iAT1W
+EztbBLToxRjmLg36ukqN6MZaoVGaSmLXr920/OLVza6ZbFxhVgvXDBp3XPU6alS1
+njOsqXUomnav0HpXABuREzH9QoghRwUQAS9Zu8c62eFYTBtscbaY790DglijMtyQ
+obamHuELAgMBAAECggEBALGnokJuqiz7mTj2NSdl+6TVEOuyPbiJKpV/J4cm1XEh
+ye9qaTQcCRhH3UmcWrG75jM9KevloLRY8A1x1/lUMhtA+XJWGTU9k6a8BLut3nT4
+3X87jNTMQgSczEXNe9WudmZcxhN7rVVtOOdTpt1pP0cnCWna5HTf0D8cuLvM975j
+r1YGTjKsCF1W+tp6ZAIIMfJkUI2qBRKvSxVCSs1vZBraox3yUVnq9oRLHxZZoqOd
+d51G5phRtn6ReVPBdT8fGUBEGg3jKxTu2/vLQMUyHy0hyCAM20gzOP4FIc2g+QZU
+y42byAuc89m0OrdRWsmzHCOxcq9DwY9npaz1RscR/2ECgYEA9bHJQ0Y1afpS5gn2
+KnXenRIw9oal1utQZnohCEJ4um+K/BCEHtDnI825LPNf34IKM2rSmssvHrYN51o0
+92j9lHHXsf6MVluwsTsIu8MtNaJ1BLt96dub4ScGT6vvzObKTwsajUfIHk+FNsKq
+zps8yh1q0qyyfAcvR82+Xr6JIsMCgYEA1d+RHGewi/Ub/GCG99A1KFKsgbiIJnWB
+IFmrcyPWignhzDUcw2SV9XqAzeK8EOIHNq3e5U/tkA7aCWxtLb5UsQ8xvmwQY2cy
+X2XvSdIhO4K2PgRLgjlzZ8RHSULglqyjB2i6TjwjFl8TsRzYr6JlV6+2cMujw4Bl
+g3a8gz071BkCgYBLP7BMkmw5kRliqxph1sffg3rLhmG0eU2elTkYtoMTVqZSnRxZ
+89FW/eMBCWkLo2BMbyMhlalQ1qFbgh1GyTkhBdzx/uwsZtiu7021dAmcq6z7ThE6
+VrBfPPyJ2jcPon/DxbrUGnAIGILMSsLVlGYB4RCehZYEto6chz8O9Xw60QKBgCnd
+us1BqviqwZC04JbQJie/j09RbS2CIQXRJ9PBNzUMXCwaVYgWP5ivI1mqQcBYTqsw
+fAqNi+aAUcQ4emLS+Ec0vzsUclzTDbRJAv+DZ8f7fWtEcfeLAYFVldLMiaRVJRDF
+OnsoIII3mGY6TFyNQKNanS8VXfheQQDsFFjoera5AoGBALXYEXkESXpw4LT6qJFz
+ktQuTZDfS6LtR14/+NkYL9c5wBC4Otkg4bNbT8xGlUjethRfpkm8xRTB6zfC1/p/
+Cg6YU1cwqlkRurAhE3PEv1dCc1IDbzou8xnwqHrd6sGPDQmQ3aEtU5eJhDZKIZfx
+nQqPGK92+Jtne7+W1mFZooxs
+-----END PRIVATE KEY-----
diff --git a/bouncy-castle/bcfips-nar-test/pom.xml b/bouncy-castle/bcfips-nar-test/pom.xml
new file mode 100644
index 0000000..d0e9722
--- /dev/null
+++ b/bouncy-castle/bcfips-nar-test/pom.xml
@@ -0,0 +1,102 @@
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.pulsar</groupId>
+    <artifactId>bouncy-castle-parent</artifactId>
+    <version>2.6.0-SNAPSHOT</version>
+    <relativePath>..</relativePath>
+  </parent>
+
+  <artifactId>bcfips-nar-test</artifactId>
+  <name>Pulsar Bouncy Castle FIPS Nar Test</name>
+  <description> Broker and client runs auth with nar load BC FIPS version</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.pulsar</groupId>
+      <artifactId>testmocks</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>pulsar-broker</artifactId>
+      <version>${project.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>${project.groupId}</groupId>
+          <artifactId>bouncy-castle-bc-shaded</artifactId>
+        </exclusion>
+      </exclusions>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>pulsar-broker</artifactId>
+      <version>${project.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>${project.groupId}</groupId>
+          <artifactId>bouncy-castle-bc-shaded</artifactId>
+        </exclusion>
+      </exclusions>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-deploy-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <executions>
+          <execution>
+            <phase>compile</phase>
+            <goals>
+              <goal>run</goal>
+            </goals>
+            <configuration>
+              <tasks>
+                <echo>copy test examples package</echo>
+                <mkdir dir="${basedir}/src/test/resources"/>
+                <copy file="${basedir}/../bcfips/target/bouncy-castle-bcfips-${project.version}.nar" tofile="${basedir}/src/test/resources/bouncy-castle-bcfips.nar"/>
+              </tasks>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+
+    </plugins>
+  </build>
+</project>
diff --git a/bouncy-castle/bcfips-nar-test/src/test/java/org/apache/pulsar/client/TlsProducerConsumerBase.java b/bouncy-castle/bcfips-nar-test/src/test/java/org/apache/pulsar/client/TlsProducerConsumerBase.java
new file mode 100644
index 0000000..959fe8e
--- /dev/null
+++ b/bouncy-castle/bcfips-nar-test/src/test/java/org/apache/pulsar/client/TlsProducerConsumerBase.java
@@ -0,0 +1,129 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.pulsar.client;
+
+import static org.mockito.Mockito.spy;
+
+import com.google.common.collect.Sets;
+import java.net.URL;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.pulsar.client.admin.PulsarAdmin;
+import org.apache.pulsar.client.api.ClientBuilder;
+import org.apache.pulsar.client.api.ProducerConsumerBase;
+import org.apache.pulsar.client.api.PulsarClient;
+import org.apache.pulsar.client.impl.auth.AuthenticationTls;
+import org.apache.pulsar.common.policies.data.ClusterData;
+import org.apache.pulsar.common.policies.data.TenantInfo;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+
+@Slf4j
+public class TlsProducerConsumerBase extends ProducerConsumerBase {
+    protected final String TLS_TRUST_CERT_FILE_PATH = "./src/test/resources/authentication/tls/cacert.pem";
+    protected final String TLS_CLIENT_CERT_FILE_PATH = "./src/test/resources/authentication/tls/client-cert.pem";
+    protected final String TLS_CLIENT_KEY_FILE_PATH = "./src/test/resources/authentication/tls/client-key.pem";
+    protected final String TLS_SERVER_CERT_FILE_PATH = "./src/test/resources/authentication/tls/broker-cert.pem";
+    protected final String TLS_SERVER_KEY_FILE_PATH = "./src/test/resources/authentication/tls/broker-key.pem";
+    private final String clusterName = "use";
+
+    @BeforeMethod
+    @Override
+    protected void setup() throws Exception {
+        // TLS configuration for Broker
+        internalSetUpForBroker();
+
+        // Start Broker
+        super.init();
+    }
+
+    @AfterMethod
+    @Override
+    protected void cleanup() throws Exception {
+        super.internalCleanup();
+    }
+
+    protected void internalSetUpForBroker() throws Exception {
+        conf.setBrokerServicePortTls(Optional.of(0));
+        conf.setWebServicePortTls(Optional.of(0));
+        conf.setTlsCertificateFilePath(TLS_SERVER_CERT_FILE_PATH);
+        conf.setTlsKeyFilePath(TLS_SERVER_KEY_FILE_PATH);
+        conf.setTlsTrustCertsFilePath(TLS_TRUST_CERT_FILE_PATH);
+        conf.setClusterName(clusterName);
+        conf.setTlsRequireTrustedClientCertOnConnect(true);
+        Set<String> tlsProtocols = Sets.newConcurrentHashSet();
+        tlsProtocols.add("TLSv1.2");
+        conf.setTlsProtocols(tlsProtocols);
+
+        // load bcfips in
+        URL bouncyCastleUrl = this.getClass().getClassLoader().getResource("bouncy-castle-bcfips.nar");
+
+        Path narPath;
+        try {
+            narPath = Paths.get(bouncyCastleUrl.toURI());
+        } catch (Exception e) {
+            log.error("failed to get Bouncy Castle FIPS Path, url: {}. Exception: ", bouncyCastleUrl, e);
+            return;
+        }
+        String bcNarDir = narPath.toFile().getParent();
+        System.setProperty("BcPath", bcNarDir);
+    }
+
+    protected void internalSetUpForClient(boolean addCertificates, String lookupUrl) throws Exception {
+        if (pulsarClient != null) {
+            pulsarClient.close();
+        }
+
+        ClientBuilder clientBuilder = PulsarClient.builder().serviceUrl(lookupUrl)
+                .tlsTrustCertsFilePath(TLS_TRUST_CERT_FILE_PATH).enableTls(true).allowTlsInsecureConnection(false)
+                .operationTimeout(1000, TimeUnit.MILLISECONDS);
+        if (addCertificates) {
+            Map<String, String> authParams = new HashMap<>();
+            authParams.put("tlsCertFile", TLS_CLIENT_CERT_FILE_PATH);
+            authParams.put("tlsKeyFile", TLS_CLIENT_KEY_FILE_PATH);
+            clientBuilder.authentication(AuthenticationTls.class.getName(), authParams);
+        }
+        pulsarClient = clientBuilder.build();
+    }
+
+    protected void internalSetUpForNamespace() throws Exception {
+        Map<String, String> authParams = new HashMap<>();
+        authParams.put("tlsCertFile", TLS_CLIENT_CERT_FILE_PATH);
+        authParams.put("tlsKeyFile", TLS_CLIENT_KEY_FILE_PATH);
+
+        if (admin != null) {
+            admin.close();
+        }
+
+        admin = spy(PulsarAdmin.builder().serviceHttpUrl(brokerUrlTls.toString())
+                .tlsTrustCertsFilePath(TLS_TRUST_CERT_FILE_PATH).allowTlsInsecureConnection(false)
+                .authentication(AuthenticationTls.class.getName(), authParams).build());
+        admin.clusters().createCluster(clusterName, new ClusterData(brokerUrl.toString(), brokerUrlTls.toString(),
+                pulsar.getBrokerServiceUrl(), pulsar.getBrokerServiceUrlTls()));
+        admin.tenants().createTenant("my-property",
+                new TenantInfo(Sets.newHashSet("appid1", "appid2"), Sets.newHashSet("use")));
+        admin.namespaces().createNamespace("my-property/my-ns");
+    }
+}
diff --git a/bouncy-castle/bcfips-nar-test/src/test/java/org/apache/pulsar/client/TlsProducerConsumerTest.java b/bouncy-castle/bcfips-nar-test/src/test/java/org/apache/pulsar/client/TlsProducerConsumerTest.java
new file mode 100644
index 0000000..85ee130
--- /dev/null
+++ b/bouncy-castle/bcfips-nar-test/src/test/java/org/apache/pulsar/client/TlsProducerConsumerTest.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.client;
+
+import java.util.Arrays;
+import java.util.concurrent.TimeUnit;
+import org.apache.pulsar.client.api.Consumer;
+import org.apache.pulsar.client.api.Message;
+import org.apache.pulsar.client.api.Producer;
+import org.apache.pulsar.client.api.SubscriptionType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class TlsProducerConsumerTest extends TlsProducerConsumerBase {
+    private static final Logger log = LoggerFactory.getLogger(TlsProducerConsumerTest.class);
+
+    /**
+     * verifies that messages whose size is larger than 2^14 bytes (max size of single TLS chunk) can be
+     * produced/consumed
+     *
+     * @throws Exception
+     */
+    @Test(timeOut = 30000)
+    public void testTlsLargeSizeMessage() throws Exception {
+        log.info("-- Starting {} test --", methodName);
+
+        final int MESSAGE_SIZE = 16 * 1024 + 1;
+        log.info("-- message size --", MESSAGE_SIZE);
+
+        internalSetUpForClient(true, pulsar.getBrokerServiceUrlTls());
+        internalSetUpForNamespace();
+
+        Consumer<byte[]> consumer = pulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic1")
+                .subscriptionName("my-subscriber-name").subscribe();
+
+        Producer<byte[]> producer = pulsarClient.newProducer().topic("persistent://my-property/use/my-ns/my-topic1")
+                .create();
+        for (int i = 0; i < 10; i++) {
+            byte[] message = new byte[MESSAGE_SIZE];
+            Arrays.fill(message, (byte) i);
+            producer.send(message);
+        }
+
+        Message<byte[]> msg = null;
+        for (int i = 0; i < 10; i++) {
+            msg = consumer.receive(5, TimeUnit.SECONDS);
+            byte[] expected = new byte[MESSAGE_SIZE];
+            Arrays.fill(expected, (byte) i);
+            Assert.assertEquals(expected, msg.getData());
+        }
+        // Acknowledge the consumption of all messages at once
+        consumer.acknowledgeCumulative(msg);
+        consumer.close();
+        log.info("-- Exiting {} test --", methodName);
+    }
+
+    @Test(timeOut = 30000)
+    public void testTlsClientAuthOverBinaryProtocol() throws Exception {
+        log.info("-- Starting {} test --", methodName);
+
+        final int MESSAGE_SIZE = 16 * 1024 + 1;
+        log.info("-- message size --", MESSAGE_SIZE);
+        internalSetUpForNamespace();
+
+        // Test 1 - Using TLS on binary protocol without sending certs - expect failure
+        internalSetUpForClient(false, pulsar.getBrokerServiceUrlTls());
+        try {
+            pulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic1")
+                    .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Exclusive).subscribe();
+            Assert.fail("Server should have failed the TLS handshake since client didn't .");
+        } catch (Exception ex) {
+            // OK
+        }
+
+        // Test 2 - Using TLS on binary protocol - sending certs
+        internalSetUpForClient(true, pulsar.getBrokerServiceUrlTls());
+        try {
+            pulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic1")
+                    .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Exclusive).subscribe();
+        } catch (Exception ex) {
+            Assert.fail("Should not fail since certs are sent.");
+        }
+    }
+
+    @Test(timeOut = 30000)
+    public void testTlsClientAuthOverHTTPProtocol() throws Exception {
+        log.info("-- Starting {} test --", methodName);
+
+        final int MESSAGE_SIZE = 16 * 1024 + 1;
+        log.info("-- message size --", MESSAGE_SIZE);
+        internalSetUpForNamespace();
+
+        // Test 1 - Using TLS on https without sending certs - expect failure
+        internalSetUpForClient(false, pulsar.getWebServiceAddressTls());
+        try {
+            pulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic1")
+                    .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Exclusive).subscribe();
+            Assert.fail("Server should have failed the TLS handshake since client didn't .");
+        } catch (Exception ex) {
+            // OK
+        }
+
+        // Test 2 - Using TLS on https - sending certs
+        internalSetUpForClient(true, pulsar.getWebServiceAddressTls());
+        try {
+            pulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic1")
+                    .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Exclusive).subscribe();
+        } catch (Exception ex) {
+            Assert.fail("Should not fail since certs are sent.");
+        }
+    }
+}
diff --git a/bouncy-castle/bcfips-nar-test/src/test/resources/authentication/tls/broker-cert.pem b/bouncy-castle/bcfips-nar-test/src/test/resources/authentication/tls/broker-cert.pem
new file mode 100644
index 0000000..69ad71c
--- /dev/null
+++ b/bouncy-castle/bcfips-nar-test/src/test/resources/authentication/tls/broker-cert.pem
@@ -0,0 +1,73 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            88:08:98:b3:13:d8:00:97
+        Signature Algorithm: sha1WithRSAEncryption
+        Issuer: C=US, ST=CA, O=Apache, OU=Pulsar Incubator, CN=localhost
+        Validity
+            Not Before: Feb 17 02:06:21 2018 GMT
+            Not After : Nov 16 00:00:00 2030 GMT
+        Subject: C=US, ST=CA, O=Apache, OU=Apache Pulsar, CN=localhost
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (2048 bit)
+                Modulus (2048 bit):
+                    00:af:bf:b7:2d:98:ad:9d:f6:da:a3:13:d4:62:0f:
+                    98:be:1c:a2:89:22:ba:6f:d5:fd:1f:67:e3:91:03:
+                    98:80:81:0e:ed:d8:f6:70:7f:2c:36:68:3d:53:ea:
+                    58:3a:a6:d5:89:66:4b:bd:1e:57:71:13:6d:4b:11:
+                    e5:40:a5:76:84:24:92:40:58:80:96:c9:1f:2c:c4:
+                    55:eb:a3:79:73:70:5c:37:9a:89:ed:2f:ba:6b:e3:
+                    82:7c:69:4a:02:54:8b:81:5e:3c:bf:4c:8a:cb:ea:
+                    2c:5e:83:e7:b7:10:08:5f:82:58:a3:89:d1:da:92:
+                    ba:2a:28:ee:30:28:3f:5b:ae:10:71:96:c7:e1:12:
+                    c5:b0:1a:ad:44:6f:44:3a:11:4a:9a:3c:0f:8d:06:
+                    80:7b:34:ef:3f:6c:f4:5e:c5:44:54:1e:c8:dd:c7:
+                    80:85:80:d9:68:e6:c6:53:03:77:e1:fe:18:61:07:
+                    77:05:4c:ed:59:bc:5d:41:38:6a:ef:5d:a1:b2:60:
+                    98:d4:48:28:95:02:8a:0e:fd:cf:7b:1b:d2:11:cc:
+                    10:0c:50:73:d7:cc:38:6c:83:dd:79:26:aa:90:c8:
+                    9b:84:86:bc:59:e9:62:69:f4:98:1b:c4:80:78:7e:
+                    a0:1a:81:9d:d2:e1:66:dd:c4:cc:fc:63:04:ac:ec:
+                    a7:35
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                D3:F3:19:AE:74:B1:AF:E7:AF:08:7B:16:72:78:29:87:79:ED:30:8C
+            X509v3 Authority Key Identifier: 
+                keyid:D4:7A:CD:0F:44:1B:16:29:25:14:ED:A2:EF:13:0F:A7:46:09:78:F6
+
+    Signature Algorithm: sha1WithRSAEncryption
+        0f:04:f3:91:f2:87:19:fe:9d:f8:34:5a:24:4a:00:d1:58:bf:
+        1e:b2:77:67:07:bc:78:b5:4b:9a:4b:fd:a1:e5:dc:0e:09:84:
+        9e:59:c4:dd:cf:f7:2e:bf:da:f3:31:36:6b:81:6e:a2:88:76:
+        e4:2e:0b:36:44:82:36:8f:80:93:f4:9e:fc:ed:85:d0:97:da:
+        0f:fb:c9:b9:8b:da:ae:07:3d:4f:82:b7:0c:25:22:63:12:6b:
+        0a:e9:c4:12:a4:5c:ed:11:12:cc:fe:b0:2e:d4:c1:ec:79:01:
+        60:ea:cc:cc:e5:66:cc:57:f6:55:a9:09:4c:63:01:e9:b4:2e:
+        73:a5
+-----BEGIN CERTIFICATE-----
+MIIDLjCCApegAwIBAgIJAIgImLMT2ACXMA0GCSqGSIb3DQEBBQUAMFoxCzAJBgNV
+BAYTAlVTMQswCQYDVQQIEwJDQTEPMA0GA1UEChMGQXBhY2hlMRkwFwYDVQQLExBQ
+dWxzYXIgSW5jdWJhdG9yMRIwEAYDVQQDEwlsb2NhbGhvc3QwHhcNMTgwMjE3MDIw
+NjIxWhcNMzAxMTE2MDAwMDAwWjBXMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex
+DzANBgNVBAoTBkFwYWNoZTEWMBQGA1UECxMNQXBhY2hlIFB1bHNhcjESMBAGA1UE
+AxMJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr7+3
+LZitnfbaoxPUYg+YvhyiiSK6b9X9H2fjkQOYgIEO7dj2cH8sNmg9U+pYOqbViWZL
+vR5XcRNtSxHlQKV2hCSSQFiAlskfLMRV66N5c3BcN5qJ7S+6a+OCfGlKAlSLgV48
+v0yKy+osXoPntxAIX4JYo4nR2pK6KijuMCg/W64QcZbH4RLFsBqtRG9EOhFKmjwP
+jQaAezTvP2z0XsVEVB7I3ceAhYDZaObGUwN34f4YYQd3BUztWbxdQThq712hsmCY
+1EgolQKKDv3PexvSEcwQDFBz18w4bIPdeSaqkMibhIa8WeliafSYG8SAeH6gGoGd
+0uFm3cTM/GMErOynNQIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQf
+Fh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU0/MZrnSx
+r+evCHsWcngph3ntMIwwHwYDVR0jBBgwFoAU1HrND0QbFiklFO2i7xMPp0YJePYw
+DQYJKoZIhvcNAQEFBQADgYEADwTzkfKHGf6d+DRaJEoA0Vi/HrJ3Zwe8eLVLmkv9
+oeXcDgmEnlnE3c/3Lr/a8zE2a4Fuooh25C4LNkSCNo+Ak/Se/O2F0JfaD/vJuYva
+rgc9T4K3DCUiYxJrCunEEqRc7RESzP6wLtTB7HkBYOrMzOVmzFf2VakJTGMB6bQu
+c6U=
+-----END CERTIFICATE-----
diff --git a/bouncy-castle/bcfips-nar-test/src/test/resources/authentication/tls/broker-key.pem b/bouncy-castle/bcfips-nar-test/src/test/resources/authentication/tls/broker-key.pem
new file mode 100644
index 0000000..004bf8e
--- /dev/null
+++ b/bouncy-castle/bcfips-nar-test/src/test/resources/authentication/tls/broker-key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCvv7ctmK2d9tqj
+E9RiD5i+HKKJIrpv1f0fZ+ORA5iAgQ7t2PZwfyw2aD1T6lg6ptWJZku9HldxE21L
+EeVApXaEJJJAWICWyR8sxFXro3lzcFw3montL7pr44J8aUoCVIuBXjy/TIrL6ixe
+g+e3EAhfglijidHakroqKO4wKD9brhBxlsfhEsWwGq1Eb0Q6EUqaPA+NBoB7NO8/
+bPRexURUHsjdx4CFgNlo5sZTA3fh/hhhB3cFTO1ZvF1BOGrvXaGyYJjUSCiVAooO
+/c97G9IRzBAMUHPXzDhsg915JqqQyJuEhrxZ6WJp9JgbxIB4fqAagZ3S4WbdxMz8
+YwSs7Kc1AgMBAAECggEAAaWEK9MwXTiA1+JJrRmETtOp2isPIBkbI/4vLZ6hASM0
+ZpoPxQIMAf58BJs/dF03xu/EaeMs4oxSC9ABG9fxAk/tZtjta3w65Ip6W5jOfHxj
+AMpb3HMEBhq9kDjUTq1IGVAutYQcEMkC3WfS9e4ahfqMpguWgbu6LsbvZFgcL9mv
+pGnKv9YVe6Xk6isvqtq6G1af0rd7c//xF0i0e/qEo83Buok3gLEZOELZbcRxjUYc
+jnyglnXnwkGjuL4E3wgS3l73ZKsb6+AYoqhMPVz8t4/PN3tTrsBJKOSYo8KzIm0U
+ek9T8XmPbP0cuheRxp9Dp8TXJJQZK0N9jz+EL0ogQQKBgQDnavm8GpR4pap9cDOc
++YI5s823b507pNdSU8elO9gLsP0JlFzv+sqghVko29r85D7Vn3MkgYTy0S4ANLCs
+0NFDY8N2QH6U1dTkk1QXZydVZDuKJ5SSpC4v+Vafl8yDxhB4Nlxhbm9vJEMfLcXh
+2kL6UlAuFDtYD0AdczwnHu5DjQKBgQDCauocm55FpcyDMMBO2CjurxcjBYS3S1xT
+Bz+sPtxJLjlKbAt8kSHUQcCcX9zhrQBfsT38LATCmKaOFqUW5/PPh2LcrxiMqlL1
+OJBUJ3Te2LTjlUn8r+DHv/69UIh5tchwRr3YgB0DuIs7jfmr4VfiOWTBtPVhoGFR
+1Wt60j30SQKBgHzreS26J2VNAFBALgxRf6OIVMbtgDG/FOCDCyU9vazp+F2gcd61
+QYYPFYcBzx9uUiDctroBFHRCyJMh3jEbc6ruAogl3m6XUxmkEeOkMk5dEerM3N2f
+tLL+5Gy385U6aI+LwKhzhcG4EGeXPNdjC362ykNldnddnB2Jo/H2N2XNAoGAdnft
+xpbxP+GDGKIZXTIM5zzcLWQMdiC+1n1BSHVZiGJZWMczzKknYw7aDq+/iekApE79
+xW8RS373ZvfXi3i2Mcx+6pjrrbOQL4tTL2SHq8+DknaDCi4mG7IbyUKMlxW1WO1S
+e929UGogtZ6S+DCte9WbVwosyFuRUetpvgLk67kCgYBWetihZjgBWrqVYT24TTRH
+KxzSzH1JgzzF9qgTdlhXDv9hC+Kc0uTKsgViesDqVuCOjkwzY5OQr9c6duO0fwwP
+qNk/qltdgjMC5iiv7duyukfbEuqKEdGGer9HFb7en96dZdVQJpYHaaslAGurtD80
+ejCQZgzR2XaHSuIQb0IUVQ==
+-----END PRIVATE KEY-----
diff --git a/bouncy-castle/bcfips-nar-test/src/test/resources/authentication/tls/cacert.pem b/bouncy-castle/bcfips-nar-test/src/test/resources/authentication/tls/cacert.pem
new file mode 100644
index 0000000..55e9067
--- /dev/null
+++ b/bouncy-castle/bcfips-nar-test/src/test/resources/authentication/tls/cacert.pem
@@ -0,0 +1,62 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            88:08:98:b3:13:d8:00:94
+        Signature Algorithm: sha1WithRSAEncryption
+        Issuer: C=US, ST=CA, O=Apache, OU=Pulsar Incubator, CN=localhost
+        Validity
+            Not Before: Feb 17 01:37:33 2018 GMT
+            Not After : Feb 16 01:37:33 2021 GMT
+        Subject: C=US, ST=CA, O=Apache, OU=Pulsar Incubator, CN=localhost
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:ea:16:8d:a5:b1:19:61:34:54:07:02:60:4e:6d:
+                    54:92:08:fd:fb:23:79:9c:05:bf:14:f7:bc:aa:db:
+                    2b:42:a4:35:74:86:e3:00:ad:8b:18:79:73:7d:f2:
+                    d1:74:dd:74:bc:b8:a2:4c:80:c9:f3:80:ce:bf:f8:
+                    6d:97:f5:05:4f:f4:b2:99:50:e8:d8:b0:c4:57:a0:
+                    e7:dc:82:57:75:2a:a2:02:21:76:f7:37:c2:dc:7c:
+                    4c:36:a6:73:6f:dc:75:48:72:ad:fa:98:02:70:b2:
+                    5e:a2:83:cc:c3:8d:20:a7:1e:bc:d7:1e:c1:d1:7e:
+                    39:35:4b:f5:be:6b:c1:0f:f9
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                D4:7A:CD:0F:44:1B:16:29:25:14:ED:A2:EF:13:0F:A7:46:09:78:F6
+            X509v3 Authority Key Identifier: 
+                keyid:D4:7A:CD:0F:44:1B:16:29:25:14:ED:A2:EF:13:0F:A7:46:09:78:F6
+                DirName:/C=US/ST=CA/O=Apache/OU=Pulsar Incubator/CN=localhost
+                serial:88:08:98:B3:13:D8:00:94
+
+            X509v3 Basic Constraints: 
+                CA:TRUE
+    Signature Algorithm: sha1WithRSAEncryption
+        5e:30:c5:7b:30:3e:1e:16:cd:ba:66:f1:2a:19:13:8a:1a:00:
+        08:f4:1e:8c:e4:3d:57:13:65:96:bf:07:58:55:52:37:3e:aa:
+        2c:19:de:ee:c3:92:6e:79:f3:06:0e:9a:7b:e0:02:50:c3:ef:
+        3b:84:ea:8f:e0:f0:16:a6:a6:67:8b:be:73:0e:5d:f7:88:39:
+        d3:d4:df:85:ad:7c:c1:4f:fa:55:55:6f:c2:48:4e:8e:82:fa:
+        72:3b:8e:9d:dc:f7:2e:9d:47:8e:e5:c9:a2:ee:b1:76:94:15:
+        7c:7a:62:bc:06:45:fa:61:2e:33:8c:18:3e:e9:d5:90:a5:a6:
+        80:5a
+-----BEGIN CERTIFICATE-----
+MIIC8jCCAlugAwIBAgIJAIgImLMT2ACUMA0GCSqGSIb3DQEBBQUAMFoxCzAJBgNV
+BAYTAlVTMQswCQYDVQQIEwJDQTEPMA0GA1UEChMGQXBhY2hlMRkwFwYDVQQLExBQ
+dWxzYXIgSW5jdWJhdG9yMRIwEAYDVQQDEwlsb2NhbGhvc3QwHhcNMTgwMjE3MDEz
+NzMzWhcNMjEwMjE2MDEzNzMzWjBaMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex
+DzANBgNVBAoTBkFwYWNoZTEZMBcGA1UECxMQUHVsc2FyIEluY3ViYXRvcjESMBAG
+A1UEAxMJbG9jYWxob3N0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDqFo2l
+sRlhNFQHAmBObVSSCP37I3mcBb8U97yq2ytCpDV0huMArYsYeXN98tF03XS8uKJM
+gMnzgM6/+G2X9QVP9LKZUOjYsMRXoOfcgld1KqICIXb3N8LcfEw2pnNv3HVIcq36
+mAJwsl6ig8zDjSCnHrzXHsHRfjk1S/W+a8EP+QIDAQABo4G/MIG8MB0GA1UdDgQW
+BBTUes0PRBsWKSUU7aLvEw+nRgl49jCBjAYDVR0jBIGEMIGBgBTUes0PRBsWKSUU
+7aLvEw+nRgl49qFepFwwWjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMQ8wDQYD
+VQQKEwZBcGFjaGUxGTAXBgNVBAsTEFB1bHNhciBJbmN1YmF0b3IxEjAQBgNVBAMT
+CWxvY2FsaG9zdIIJAIgImLMT2ACUMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEF
+BQADgYEAXjDFezA+HhbNumbxKhkTihoACPQejOQ9VxNllr8HWFVSNz6qLBne7sOS
+bnnzBg6ae+ACUMPvO4Tqj+DwFqamZ4u+cw5d94g509Tfha18wU/6VVVvwkhOjoL6
+cjuOndz3Lp1HjuXJou6xdpQVfHpivAZF+mEuM4wYPunVkKWmgFo=
+-----END CERTIFICATE-----
diff --git a/bouncy-castle/bcfips-nar-test/src/test/resources/authentication/tls/client-cert.pem b/bouncy-castle/bcfips-nar-test/src/test/resources/authentication/tls/client-cert.pem
new file mode 100644
index 0000000..61847f2
--- /dev/null
+++ b/bouncy-castle/bcfips-nar-test/src/test/resources/authentication/tls/client-cert.pem
@@ -0,0 +1,73 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            88:08:98:b3:13:d8:00:99
+        Signature Algorithm: sha1WithRSAEncryption
+        Issuer: C=US, ST=CA, O=Apache, OU=Pulsar Incubator, CN=localhost
+        Validity
+            Not Before: Feb 17 02:50:05 2018 GMT
+            Not After : Nov 16 00:00:00 2030 GMT
+        Subject: C=US, ST=CA, O=Apache, OU=Apache Pulsar, CN=superUser
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (2048 bit)
+                Modulus (2048 bit):
+                    00:cd:43:7d:98:40:f9:b0:5b:bc:ae:db:c0:0b:ad:
+                    26:90:96:e0:62:38:ed:68:b1:70:46:3b:de:44:f9:
+                    14:51:86:10:eb:ca:90:e7:88:e8:f9:91:85:e0:dd:
+                    b5:b4:14:b9:78:e3:86:d5:54:6d:68:ec:14:92:b4:
+                    f8:22:5b:05:3d:ed:31:25:65:08:05:84:ca:e6:0c:
+                    21:12:58:32:c7:1a:60:a3:4f:d2:4a:9e:28:19:7c:
+                    45:84:00:8c:89:dc:de:8a:e5:4f:88:91:cc:a4:f1:
+                    81:45:4c:7d:c2:ff:e2:c1:89:c6:12:73:95:e2:36:
+                    bd:db:ae:8b:5a:68:6a:90:51:de:2b:88:5f:aa:67:
+                    f4:a8:e3:63:dc:be:19:82:cc:9d:7f:e6:8d:fb:82:
+                    be:22:01:3d:56:13:3b:5b:04:b4:e8:c5:18:e6:2e:
+                    0d:fa:ba:4a:8d:e8:c6:5a:a1:51:9a:4a:62:d7:af:
+                    dd:b4:fc:e2:d5:cd:ae:99:6c:5c:61:56:0b:d7:0c:
+                    1a:77:5c:f5:3a:6a:54:b5:9e:33:ac:a9:75:28:9a:
+                    76:af:d0:7a:57:00:1b:91:13:31:fd:42:88:21:47:
+                    05:10:01:2f:59:bb:c7:3a:d9:e1:58:4c:1b:6c:71:
+                    b6:98:ef:dd:03:82:58:a3:32:dc:90:a1:b6:a6:1e:
+                    e1:0b
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                53:7C:D5:D1:52:97:9A:D6:D5:EA:EC:B6:0C:9B:43:39:19:73:F6:2C
+            X509v3 Authority Key Identifier: 
+                keyid:D4:7A:CD:0F:44:1B:16:29:25:14:ED:A2:EF:13:0F:A7:46:09:78:F6
+
+    Signature Algorithm: sha1WithRSAEncryption
+        e4:03:82:ff:be:df:7c:73:2a:c5:8f:7d:87:ab:95:b1:2b:e5:
+        f7:41:22:4f:28:54:84:7a:cc:fe:70:89:0f:48:e5:8a:17:e1:
+        44:ad:12:e9:a1:3a:c7:84:55:f0:7c:29:52:0a:a1:ab:cc:5b:
+        31:e5:b2:37:73:3a:8d:f2:f1:fb:e8:f6:a2:b9:ef:11:10:f8:
+        31:43:8f:af:ce:09:f4:cb:96:0e:d4:58:42:6e:86:ab:b9:03:
+        19:8b:4a:6e:ef:50:c0:7e:c9:0b:1d:2b:42:bf:eb:d0:06:05:
+        84:ea:5a:8a:22:5c:56:fa:da:2a:9f:8a:b2:90:66:8c:5e:01:
+        87:45
+-----BEGIN CERTIFICATE-----
+MIIDLjCCApegAwIBAgIJAIgImLMT2ACZMA0GCSqGSIb3DQEBBQUAMFoxCzAJBgNV
+BAYTAlVTMQswCQYDVQQIEwJDQTEPMA0GA1UEChMGQXBhY2hlMRkwFwYDVQQLExBQ
+dWxzYXIgSW5jdWJhdG9yMRIwEAYDVQQDEwlsb2NhbGhvc3QwHhcNMTgwMjE3MDI1
+MDA1WhcNMzAxMTE2MDAwMDAwWjBXMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex
+DzANBgNVBAoTBkFwYWNoZTEWMBQGA1UECxMNQXBhY2hlIFB1bHNhcjESMBAGA1UE
+AxMJc3VwZXJVc2VyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzUN9
+mED5sFu8rtvAC60mkJbgYjjtaLFwRjveRPkUUYYQ68qQ54jo+ZGF4N21tBS5eOOG
+1VRtaOwUkrT4IlsFPe0xJWUIBYTK5gwhElgyxxpgo0/SSp4oGXxFhACMidzeiuVP
+iJHMpPGBRUx9wv/iwYnGEnOV4ja9266LWmhqkFHeK4hfqmf0qONj3L4Zgsydf+aN
++4K+IgE9VhM7WwS06MUY5i4N+rpKjejGWqFRmkpi16/dtPzi1c2umWxcYVYL1wwa
+d1z1OmpUtZ4zrKl1KJp2r9B6VwAbkRMx/UKIIUcFEAEvWbvHOtnhWEwbbHG2mO/d
+A4JYozLckKG2ph7hCwIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQf
+Fh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUU3zV0VKX
+mtbV6uy2DJtDORlz9iwwHwYDVR0jBBgwFoAU1HrND0QbFiklFO2i7xMPp0YJePYw
+DQYJKoZIhvcNAQEFBQADgYEA5AOC/77ffHMqxY99h6uVsSvl90EiTyhUhHrM/nCJ
+D0jlihfhRK0S6aE6x4RV8HwpUgqhq8xbMeWyN3M6jfLx++j2ornvERD4MUOPr84J
+9MuWDtRYQm6Gq7kDGYtKbu9QwH7JCx0rQr/r0AYFhOpaiiJcVvraKp+KspBmjF4B
+h0U=
+-----END CERTIFICATE-----
diff --git a/bouncy-castle/bcfips-nar-test/src/test/resources/authentication/tls/client-key.pem b/bouncy-castle/bcfips-nar-test/src/test/resources/authentication/tls/client-key.pem
new file mode 100644
index 0000000..3835b3e
--- /dev/null
+++ b/bouncy-castle/bcfips-nar-test/src/test/resources/authentication/tls/client-key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDNQ32YQPmwW7yu
+28ALrSaQluBiOO1osXBGO95E+RRRhhDrypDniOj5kYXg3bW0FLl444bVVG1o7BSS
+tPgiWwU97TElZQgFhMrmDCESWDLHGmCjT9JKnigZfEWEAIyJ3N6K5U+Ikcyk8YFF
+TH3C/+LBicYSc5XiNr3brotaaGqQUd4riF+qZ/So42PcvhmCzJ1/5o37gr4iAT1W
+EztbBLToxRjmLg36ukqN6MZaoVGaSmLXr920/OLVza6ZbFxhVgvXDBp3XPU6alS1
+njOsqXUomnav0HpXABuREzH9QoghRwUQAS9Zu8c62eFYTBtscbaY790DglijMtyQ
+obamHuELAgMBAAECggEBALGnokJuqiz7mTj2NSdl+6TVEOuyPbiJKpV/J4cm1XEh
+ye9qaTQcCRhH3UmcWrG75jM9KevloLRY8A1x1/lUMhtA+XJWGTU9k6a8BLut3nT4
+3X87jNTMQgSczEXNe9WudmZcxhN7rVVtOOdTpt1pP0cnCWna5HTf0D8cuLvM975j
+r1YGTjKsCF1W+tp6ZAIIMfJkUI2qBRKvSxVCSs1vZBraox3yUVnq9oRLHxZZoqOd
+d51G5phRtn6ReVPBdT8fGUBEGg3jKxTu2/vLQMUyHy0hyCAM20gzOP4FIc2g+QZU
+y42byAuc89m0OrdRWsmzHCOxcq9DwY9npaz1RscR/2ECgYEA9bHJQ0Y1afpS5gn2
+KnXenRIw9oal1utQZnohCEJ4um+K/BCEHtDnI825LPNf34IKM2rSmssvHrYN51o0
+92j9lHHXsf6MVluwsTsIu8MtNaJ1BLt96dub4ScGT6vvzObKTwsajUfIHk+FNsKq
+zps8yh1q0qyyfAcvR82+Xr6JIsMCgYEA1d+RHGewi/Ub/GCG99A1KFKsgbiIJnWB
+IFmrcyPWignhzDUcw2SV9XqAzeK8EOIHNq3e5U/tkA7aCWxtLb5UsQ8xvmwQY2cy
+X2XvSdIhO4K2PgRLgjlzZ8RHSULglqyjB2i6TjwjFl8TsRzYr6JlV6+2cMujw4Bl
+g3a8gz071BkCgYBLP7BMkmw5kRliqxph1sffg3rLhmG0eU2elTkYtoMTVqZSnRxZ
+89FW/eMBCWkLo2BMbyMhlalQ1qFbgh1GyTkhBdzx/uwsZtiu7021dAmcq6z7ThE6
+VrBfPPyJ2jcPon/DxbrUGnAIGILMSsLVlGYB4RCehZYEto6chz8O9Xw60QKBgCnd
+us1BqviqwZC04JbQJie/j09RbS2CIQXRJ9PBNzUMXCwaVYgWP5ivI1mqQcBYTqsw
+fAqNi+aAUcQ4emLS+Ec0vzsUclzTDbRJAv+DZ8f7fWtEcfeLAYFVldLMiaRVJRDF
+OnsoIII3mGY6TFyNQKNanS8VXfheQQDsFFjoera5AoGBALXYEXkESXpw4LT6qJFz
+ktQuTZDfS6LtR14/+NkYL9c5wBC4Otkg4bNbT8xGlUjethRfpkm8xRTB6zfC1/p/
+Cg6YU1cwqlkRurAhE3PEv1dCc1IDbzou8xnwqHrd6sGPDQmQ3aEtU5eJhDZKIZfx
+nQqPGK92+Jtne7+W1mFZooxs
+-----END PRIVATE KEY-----
diff --git a/pulsar-sql/presto-distribution/LICENSE b/bouncy-castle/bcfips/LICENSE
similarity index 54%
copy from pulsar-sql/presto-distribution/LICENSE
copy to bouncy-castle/bcfips/LICENSE
index e1d08d1..f770bab 100644
--- a/pulsar-sql/presto-distribution/LICENSE
+++ b/bouncy-castle/bcfips/LICENSE
@@ -203,354 +203,7 @@
 ----------------------------------------------------------------------------------------------------
 
 This projects includes binary packages with the following licenses:
-
-The Apache Software License, Version 2.0
-
-  * Jackson
-    - jackson-annotations-2.8.11.jar
-    - jackson-core-2.8.11.jar
-    - jackson-databind-2.8.11.4.jar
-    - jackson-dataformat-smile-2.8.11.jar
-    - jackson-datatype-guava-2.8.11.jar
-    - jackson-datatype-guava-2.8.11.jar
-    - jackson-datatype-jdk8-2.8.11.jar
-    - jackson-datatype-jdk8-2.8.11.jar
-    - jackson-datatype-joda-2.8.11.jar
-    - jackson-datatype-jsr310-2.8.11.jar
-    - jackson-dataformat-yaml-2.8.11.jar
- * Guava
-    - guava-25.1-jre.jar
- * Google Guice
-    - guice-4.2.0.jar
-    - guice-multibindings-4.2.0.jar
- * Apache Commons
-    - commons-math3-3.6.1.jar
-    - commons-beanutils-core-1.8.3.jar
-    - commons-compress-1.19.jar
-    - commons-lang3-3.3.2.jar
-    - commons-lang3-3.4.jar
- * Netty
-    - netty-3.10.6.Final.jar
-    - netty-buffer-4.1.45.Final.jar
-    - netty-codec-4.1.45.Final.jar
-    - netty-codec-dns-4.1.45.Final.jar
-    - netty-codec-http-4.1.45.Final.jar
-    - netty-codec-socks-4.1.45.Final.jar
-    - netty-common-4.1.45.Final.jar
-    - netty-handler-4.1.45.Final.jar
-    - netty-handler-proxy-4.1.45.Final.jar
-    - netty-reactive-streams-2.0.0.jar
-    - netty-resolver-4.1.45.Final.jar
-    - netty-resolver-dns-4.1.45.Final.jar
-    - netty-tcnative-boringssl-static-2.0.26.Final.jar
-    - netty-transport-4.1.45.Final.jar
-    - netty-transport-native-epoll-4.1.45.Final.jar
-    - netty-transport-native-epoll-4.1.45.Final-linux-x86_64.jar
-    - netty-transport-native-unix-common-4.1.45.Final.jar
-    - netty-transport-native-unix-common-4.1.45.Final-linux-x86_64.jar
- * Joda Time
-    - joda-time-2.9.9.jar
-    - joda-time-2.10.1.jar
- * Jetty
-    - http2-client-9.4.11.v20180605.jar
-    - http2-common-9.4.11.v20180605.jar
-    - http2-hpack-9.4.11.v20180605.jar
-    - http2-http-client-transport-9.4.11.v20180605.jar
-    - http2-server-9.4.11.v20180605.jar
-    - jetty-alpn-client-9.4.11.v20180605.jar
-    - jetty-client-9.4.11.v20180605.jar
-    - jetty-http-9.4.11.v20180605.jar
-    - jetty-io-9.4.11.v20180605.jar
-    - jetty-jmx-9.4.11.v20180605.jar
-    - jetty-security-9.4.11.v20180605.jar
-    - jetty-server-9.4.11.v20180605.jar
-    - jetty-servlet-9.4.11.v20180605.jar
-    - jetty-util-9.4.11.v20180605.jar
-  * Asynchronous Http Client
-    - async-http-client-1.9.40.jar
-  * Apache BVal
-    - bval-core-1.1.1.jar
-    - bval-jsr-1.1.1.jar
-  * Bytecode
-    - bytecode-1.0.jar
-  * CGLIB Nodep
-    - cglib-nodep-3.2.5.jar
-  * Airlift
-    - aircompressor-0.11.jar
-    - airline-0.8.jar
-    - bootstrap-0.170.jar
-    - bootstrap-0.171.jar
-    - concurrent-0.171.jar
-    - configuration-0.171.jar
-    - configuration-0.170.jar
-    - discovery-0.171.jar
-    - discovery-server-1.29.jar
-    - event-0.171.jar
-    - http-client-0.171.jar
-    - http-server-0.171.jar
-    - jmx-0.171.jar
-    - jmx-http-0.171.jar
-    - jmx-http-rpc-0.159.jar
-    - joni-2.1.5.1.jar
-    - json-0.170.jar
-    - json-0.171.jar
-    - log-0.170.jar
-    - log-0.171.jar
-    - log-manager-0.170.jar
-    - log-manager-0.171.jar
-    - node-0.171.jar
-    - resolver-1.4.jar
-    - security-0.171.jar
-    - slice-0.35.jar
-    - stats-0.171.jar
-    - trace-token-0.171.jar
-    - units-1.0.jar
-  * Error Prone Annotations
-    - error_prone_annotations-2.1.3.jar
-  * Esri Geometry API For Java
-    - esri-geometry-api-2.1.0.jar
-  * Fastutil
-    - fastutil-6.5.9.jar
-  * J2ObjC Annotations
-    - j2objc-annotations-1.1.jar
-  * JSON Web Token Support For The JVM
-    - jjwt-0.9.0.jar
-  * Jmxutils
-    - jmxutils-1.19.jar
-  * LevelDB
-    - leveldb-0.10.jar
-    - leveldb-api-0.10.jar
-  * Log4j implemented over SLF4J
-    - log4j-over-slf4j-1.7.25.jar
-  * Lucene Common Analyzers
-    - lucene-analyzers-common-7.2.1.jar
-  * Maven
-    - maven-aether-provider-3.0.5.jar
-    - maven-artifact-3.0.5.jar
-    - maven-core-3.0.5.jar
-    - maven-compat-3.0.5.jar
-    - maven-embedder-3.0.5.jar
-    - maven-model-3.0.5.jar
-    - maven-model-builder-3.0.5.jar
-    - maven-plugin-api-3.0.5.jar
-    - maven-repository-metadata-3.0.5.jar
-    - maven-settings-3.0.5.jar
-    - maven-settings-builder-3.0.5.jar
-	- wagon-provider-api-2.4.jar
-  * OkHttp
-    - okhttp-3.9.0.jar
-    - okhttp-urlconnection-3.9.0.jar
-  * OpenCSV
-    - opencsv-2.3.jar
-  * Plexus
-    - plexus-cipher-1.7.jar
-    - plexus-classworlds-2.4.jar
-    - plexus-component-annotations-1.5.5.jar
-    - plexus-container-default-1.5.5.jar
-    - plexus-interpolation-1.14.jar
-    - plexus-sec-dispatcher-1.3.jar
-    - plexus-utils-2.0.6.jar
-  * Apache XBean :: Reflect
-    - xbean-reflect-3.4.jar
-  * Avro
-    - avro-1.9.1.jar
-    - avro-protobuf-1.9.1.jar
-  * Caffeine
-    - caffeine-2.6.2.jar
-  * Javax
-    - javax.inject-1.jar
-    - javax.inject-1.jar
-    - javax.servlet-api-3.1.0.jar
-    - javax.ws.rs-api-2.1.jar
-  * JCommander
-    - jcommander-1.48.jar
-  * FindBugs JSR305
-    - jsr305-3.0.2.jar
-  * Objenesis
-    - objenesis-2.6.jar
-  * Okio
-    - okio-1.13.0.jar
-  * Presto
-    - presto-array-0.206.jar
-    - presto-cli-0.206.jar
-    - presto-client-0.206.jar
-    - presto-geospatial-toolkit-0.206.jar
-    - presto-main-0.206.jar
-    - presto-matching-0.206.jar
-    - presto-memory-context-0.206.jar
-    - presto-parser-0.206.jar
-    - presto-spi-0.206.jar
-  * RocksDB JNI
-    - rocksdbjni-5.13.3.jar
-  * SnakeYAML
-    - snakeyaml-1.17.jar
-  * Snappy Java
-    - snappy-java-1.1.1.3.jar
-  * Bean Validation API
-    - validation-api-1.1.0.Final.jar
-  * Objectsize
-    - objectsize-0.0.12.jar
-  * Dropwizard Metrics
-    - metrics-core-3.1.0.jar
-    - metrics-graphite-3.1.0.jar
-    - metrics-jvm-3.1.0.jar
-  * Prometheus
-    - simpleclient-0.5.0.jar
-    - simpleclient_common-0.5.0.jar
-    - simpleclient_hotspot-0.5.0.jar
-    - simpleclient_servlet-0.5.0.jar
-  * LZ4
-    - lz4-java-1.5.0.jar
-  * JCTools
-    - jctools-core-2.1.2.jar
-  * Asynchronous Http Client
-    - async-http-client-2.7.0.jar
-    - async-http-client-netty-utils-2.7.0.jar
-  * Apache Bookkeeper
-    - bookkeeper-common-4.10.0.jar
-    - bookkeeper-common-allocator-4.10.0.jar
-    - bookkeeper-proto-4.10.0.jar
-    - bookkeeper-server-4.10.0.jar
-    - bookkeeper-stats-api-4.10.0.jar
-    - bookkeeper-tools-framework-4.10.0.jar
-    - circe-checksum-4.10.0.jar
-    - codahale-metrics-provider-4.10.0.jar
-    - cpu-affinity-4.10.0.jar
-    - http-server-4.10.0.jar
-    - prometheus-metrics-provider-4.10.0.jar
-  * Apache Commons
-    - commons-cli-1.2.jar
-    - commons-codec-1.10.jar
-    - commons-collections4-4.1.jar
-    - commons-configuration-1.10.jar
-    - commons-io-2.5.jar
-    - commons-lang-2.6.jar
-    - commons-logging-1.1.1.jar
-  * GSON
-    - gson-2.8.2.jar
-  * Jackson
-    - jackson-jaxrs-base-2.8.11.jar
-    - jackson-jaxrs-json-provider-2.8.11.jar
-    - jackson-module-jaxb-annotations-2.8.11.jar
-    - jackson-module-jsonSchema-2.8.11.jar
-  * Java Assist
-    - javassist-3.25.0-GA.jar
-  * Jetty
-    - jetty-http-9.4.20.v20190813.jar
-    - jetty-io-9.4.20.v20190813.jar
-    - jetty-security-9.4.20.v20190813.jar
-    - jetty-server-9.4.20.v20190813.jar
-    - jetty-servlet-9.4.20.v20190813.jar
-    - jetty-util-9.4.20.v20190813.jar
-  * Java Native Access
-    - jna-4.2.0.jar
-  * Yahoo Datasketches
-    - memory-0.8.3.jar
-    - sketches-core-0.8.3.jar
-  * Apache Zookeeper
-    - zookeeper-3.5.7.jar
-    - zookeeper-jute-3.5.7.jar
-  * Apache Yetus Audience Annotations
-    - audience-annotations-0.5.0.jar
-  * Swagger
-    - swagger-annotations-1.5.21.jar
-
-Protocol Buffers License
- * Protocol Buffers
-   - protobuf-shaded-2.1.0-incubating.jar
-   - protobuf-java-3.5.1.jar
-   - protobuf-java-util-3.5.1.jar
-
-BSD 3-clause "New" or "Revised" License
-  *  RE2J TD -- re2j-td-1.4.jar
-  *  DSL Platform JSON
-    - dsl-json-1.8.4.jar
-
-BSD License
- * ANTLR 4 Runtime -- antlr4-runtime-4.6.jar
- * ASM, a very small and fast Java bytecode manipulation framework
-    - asm-6.1.1.jar
-    - asm-analysis-6.0.jar
-    - asm-tree-6.0.jar
-    - asm-util-6.0.jar
- * JLine
-   - jline-2.14.6.jar
- * Zstd-jni
-   - zstd-jni-1.3.7-3.jar
-
-MIT License
- * Animal Sniffer Annotations
-   - animal-sniffer-annotations-1.14.jar
- * PCollections
-   - pcollections-2.1.2.jar
- * SLF4J
-   - slf4j-jdk14-1.7.25.jar
-   - slf4j-api-1.7.12.jar
-   - slf4j-api-1.7.25.jar
- * JCL 1.2 Implemented Over SLF4J
-   - jcl-over-slf4j-1.7.25.jar
- * JUL to SLF4J Bridge
-   - jul-to-slf4j-1.7.25.jar
- * Checker Qual
-   - checker-qual-2.0.0.jar
-
-CDDL - 1.0
- * OSGi Resource Locator
-    - osgi-resource-locator-1.0.1.jar
-
-CDDL-1.1 -- licenses/LICENSE-CDDL-1.1.txt
- * Java Annotations API
-   - javax.annotation-api-1.2.jar
-   - javax.annotation-api-1.3.1.jar
-   - javax.activation-1.2.0.jar
- * HK2 - Dependency Injection Kernel
-   - hk2-api-2.5.0-b42.jar
-   - hk2-locator-2.5.0-b42.jar
-   - hk2-utils-2.5.0-b42.jar
- * Jersey
-    - jaxrs-0.171.jar
-    - jersey-client-2.26.jar
-    - jersey-container-servlet-2.26.jar
-    - jersey-container-servlet-core-2.26.jar
-    - jersey-hk2-2.26.jar
-    - jersey-media-jaxb-2.26.jar
-    - jersey-server-2.26.jar
-    - jersey-common-2.26.jar
- * JAXB
-    - jaxb-api-2.2.6.jar
-    - jaxb-api-2.3.1.jar
-    - jaxb-impl-2.2.6.jar
-
- Eclipse Public License 1.0 -- licenses/LICENSE-AspectJ.txt
-  * Aether
-     - aether-api-1.13.1.jar
-     - aether-connector-asynchttpclient-1.13.1.jar
-     - aether-connector-file-1.13.1.jar
-     - aether-impl-1.13.1.jar
-     - aether-spi-1.13.1.jar
-     - aether-util-1.13.1.jar
-  * JTS Core
-     - jts-core-1.15.0.jar
-  *JGraphT Core
-     - jgrapht-core-0.9.0.jar
-  * Logback Core Module
-    - logback-core-1.2.3.jar
-  * MIME Streaming Extension
-    - mimepull-1.9.6.jar
-
-Public Domain (CC0) -- licenses/LICENSE-CC0.txt
- * HdrHistogram
-   - HdrHistogram-2.1.9.jar
- * AOP Alliance
-   - aopalliance-1.0.jar
- * Reactive Streams
-    - reactive-streams-1.0.2.jar
-
 Bouncy Castle License
  * Bouncy Castle -- licenses/LICENSE-bouncycastle.txt
-    - bcpkix-jdk15on-1.60.jar
-    - bcprov-jdk15on-1.60.jar
-
-Creative Commons Attribution License
- * Jcip -- licenses/LICENSE-jcip.txt
-    - jcip-annotations-1.0.jar
+    - org.bouncycastle-bcpkix-fips-1.0.1.jar
+    - org.bouncycastle-bc-fips-1.0.1.jar
diff --git a/bouncy-castle/bcfips/pom.xml b/bouncy-castle/bcfips/pom.xml
new file mode 100644
index 0000000..7b11ce2
--- /dev/null
+++ b/bouncy-castle/bcfips/pom.xml
@@ -0,0 +1,64 @@
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.pulsar</groupId>
+    <artifactId>bouncy-castle-parent</artifactId>
+    <version>2.6.0-SNAPSHOT</version>
+    <relativePath>..</relativePath>
+  </parent>
+
+  <artifactId>bouncy-castle-bcfips</artifactId>
+  <name>Apache Pulsar :: Bouncy Castle :: BC-FIPS</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>pulsar-common</artifactId>
+      <version>${project.parent.version}</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bc-fips</artifactId>
+      <version>${bouncycastlefips.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bcpkix-fips</artifactId>
+      <version>${bouncycastlefips.version}</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.nifi</groupId>
+        <artifactId>nifi-nar-maven-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/bouncy-castle/bcfips/src/main/java/org/apache/pulsar/bcloader/BouncyCastleFipsLoader.java b/bouncy-castle/bcfips/src/main/java/org/apache/pulsar/bcloader/BouncyCastleFipsLoader.java
new file mode 100644
index 0000000..984df77
--- /dev/null
+++ b/bouncy-castle/bcfips/src/main/java/org/apache/pulsar/bcloader/BouncyCastleFipsLoader.java
@@ -0,0 +1,47 @@
+/**
+ * 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.bcloader;
+
+import static org.apache.pulsar.common.util.SecurityUtility.BC_FIPS;
+
+import java.security.Provider;
+import java.security.Security;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.pulsar.common.util.BCLoader;
+import org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider;
+
+/**
+ * This is a Bouncy Castle provider Loader.
+ */
+@Slf4j
+public class BouncyCastleFipsLoader implements BCLoader {
+    public static Provider provider;
+    static {
+        if (Security.getProvider(BC_FIPS) == null) {
+            Security.addProvider(new BouncyCastleFipsProvider());
+        }
+        provider = Security.getProvider(BC_FIPS);
+        log.info("BouncyCastle Provider BC_FIPS: {}", Security.getProvider(BC_FIPS));
+    }
+
+    @Override
+    public Provider getProvider() {
+        return Security.getProvider(BC_FIPS);
+    }
+}
diff --git a/bouncy-castle/bcfips/src/main/resources/META-INF/services/bouncy-castle.yaml b/bouncy-castle/bcfips/src/main/resources/META-INF/services/bouncy-castle.yaml
new file mode 100644
index 0000000..26ca9cd
--- /dev/null
+++ b/bouncy-castle/bcfips/src/main/resources/META-INF/services/bouncy-castle.yaml
@@ -0,0 +1,22 @@
+#
+# 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.
+#
+
+name: bouncy-castle-fips
+description: loader for Bouncy Castle FIPS provider
+bcLoaderClass: org.apache.pulsar.bcloader.BouncyCastleFipsLoader
diff --git a/bouncy-castle/pom.xml b/bouncy-castle/pom.xml
new file mode 100644
index 0000000..926eb61
--- /dev/null
+++ b/bouncy-castle/pom.xml
@@ -0,0 +1,48 @@
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <packaging>pom</packaging>
+  <parent>
+    <groupId>org.apache.pulsar</groupId>
+    <artifactId>pulsar</artifactId>
+    <version>2.6.0-SNAPSHOT</version>
+    <relativePath>..</relativePath>
+  </parent>
+
+  <artifactId>bouncy-castle-parent</artifactId>
+  <name>Apache Pulsar :: Bouncy Castle :: Parent</name>
+
+  <!--make it easy for user to load Bouncy Castle and Bouncy Castle FIPS-->
+  <modules>
+    <!--2 module for nar-->
+    <module>bc</module>
+    <module>bcfips</module>
+
+    <!--a module for shaded bouncy-castle class, aimed to provide fat jars for easy operation-->
+    <module>bc-shaded</module>
+
+    <!--2 module for fips version test-->
+    <module>bcfips-include-test</module>
+    <module>bcfips-nar-test</module>
+  </modules>
+</project>
diff --git a/distribution/server/pom.xml b/distribution/server/pom.xml
index abf569f..9942b7f 100644
--- a/distribution/server/pom.xml
+++ b/distribution/server/pom.xml
@@ -146,6 +146,11 @@
           <groupId>io.grpc</groupId>
           <artifactId>*</artifactId>
         </exclusion>
+        <!-- bouncy-castle-bc-shaded already contains this-->
+        <exclusion>
+          <groupId>org.bouncycastle</groupId>
+          <artifactId>*</artifactId>
+        </exclusion>
       </exclusions>
     </dependency>
 
diff --git a/distribution/server/src/assemble/LICENSE.bin.txt b/distribution/server/src/assemble/LICENSE.bin.txt
index 3e17c87..827864d 100644
--- a/distribution/server/src/assemble/LICENSE.bin.txt
+++ b/distribution/server/src/assemble/LICENSE.bin.txt
@@ -568,12 +568,6 @@ Eclipse Public License 1.0 -- licenses/LICENSE-AspectJ.txt
 Public Domain (CC0) -- licenses/LICENSE-CC0.txt
  * Reactive Streams -- org.reactivestreams-reactive-streams-1.0.2.jar
 
-Bouncy Castle License
- * Bouncy Castle -- licenses/LICENSE-bouncycastle.txt
-    - org.bouncycastle-bcpkix-jdk15on-1.60.jar
-    - org.bouncycastle-bcprov-jdk15on-1.60.jar
-    - org.bouncycastle-bcprov-ext-jdk15on-1.60.jar
-
 Creative Commons Attribution License
  * Jcip -- licenses/LICENSE-jcip.txt
     - net.jcip-jcip-annotations-1.0.jar
diff --git a/pom.xml b/pom.xml
index 55352b7..efaa164 100644
--- a/pom.xml
+++ b/pom.xml
@@ -120,6 +120,11 @@ flexible messaging model and an intuitive client API.</description>
     <!-- examples -->
     <module>examples</module>
 
+    <!-- Bouncy Castle Provider loaders-->
+    <module>bouncy-castle</module>
+
+    <module>pulsar-client-messagecrypto-bc</module>
+
     <!-- all these 3 modules should be put at the end in this exact sequence -->
     <module>distribution</module>
     <module>docker</module>
@@ -161,6 +166,7 @@ flexible messaging model and an intuitive client API.</description>
     <commons.collections.version>3.2.2</commons.collections.version>
     <log4j2.version>2.10.0</log4j2.version>
     <bouncycastle.version>1.60</bouncycastle.version>
+    <bouncycastlefips.version>1.0.2</bouncycastlefips.version>
     <jackson.version>2.10.1</jackson.version>
     <jackson.databind.version>2.10.1</jackson.databind.version>
     <reflections.version>0.9.11</reflections.version>
@@ -939,18 +945,6 @@ flexible messaging model and an intuitive client API.</description>
       </dependency>
 
       <dependency>
-        <groupId>org.bouncycastle</groupId>
-        <artifactId>bcpkix-jdk15on</artifactId>
-        <version>${bouncycastle.version}</version>
-      </dependency>
-
-      <dependency>
-        <groupId>org.bouncycastle</groupId>
-        <artifactId>bcprov-ext-jdk15on</artifactId>
-        <version>${bouncycastle.version}</version>
-      </dependency>
-
-      <dependency>
         <groupId>net.jodah</groupId>
         <artifactId>typetools</artifactId>
         <version>${typetools.version}</version>
diff --git a/pulsar-broker-shaded/pom.xml b/pulsar-broker-shaded/pom.xml
index 4fcc51a..d79f5ea 100644
--- a/pulsar-broker-shaded/pom.xml
+++ b/pulsar-broker-shaded/pom.xml
@@ -107,6 +107,8 @@
                   <include>com.thoughtworks.paranamer:paranamer</include>
                   <include>org.apache.commons:commons-compress</include>
                   <include>org.tukaani:xz</include>
+                  <!-- bouncycastle Provider dependencies-->
+                  <include>org.bouncycastle:*</include>
                 </includes>
               </artifactSet>
               <filters>
diff --git a/pulsar-broker/pom.xml b/pulsar-broker/pom.xml
index dece2f8..9a9c4a6 100644
--- a/pulsar-broker/pom.xml
+++ b/pulsar-broker/pom.xml
@@ -72,7 +72,7 @@
     </dependency>
 
     <dependency>
-      <groupId>${project.groupId}</groupId>
+      <groupId>org.apache.pulsar</groupId>
       <artifactId>pulsar-client-original</artifactId>
       <version>${project.version}</version>
     </dependency>
@@ -163,6 +163,13 @@
       <scope>test</scope>
     </dependency>
 
+    <dependency>
+      <groupId>org.apache.pulsar</groupId>
+      <artifactId>pulsar-client-messagecrypto-bc</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+
     <!-- functions related dependencies (end) -->
 
     <dependency>
diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/SimpleProducerConsumerTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/SimpleProducerConsumerTest.java
index 612b610..ad039e1 100644
--- a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/SimpleProducerConsumerTest.java
+++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/SimpleProducerConsumerTest.java
@@ -47,8 +47,6 @@ import java.nio.file.Paths;
 import java.time.Clock;
 import java.time.Instant;
 import java.time.ZoneId;
-import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -79,11 +77,11 @@ import org.apache.pulsar.broker.service.persistent.PersistentTopic;
 import org.apache.pulsar.client.admin.PulsarAdminException;
 import org.apache.pulsar.client.impl.ClientCnx;
 import org.apache.pulsar.client.impl.ConsumerImpl;
-import org.apache.pulsar.client.impl.MessageCrypto;
 import org.apache.pulsar.client.impl.MessageIdImpl;
 import org.apache.pulsar.client.impl.MessageImpl;
 import org.apache.pulsar.client.impl.TopicMessageImpl;
 import org.apache.pulsar.client.impl.TypedMessageBuilderImpl;
+import org.apache.pulsar.client.impl.crypto.MessageCryptoBc;
 import org.apache.pulsar.common.protocol.Commands;
 import org.apache.pulsar.common.api.EncryptionContext;
 import org.apache.pulsar.common.api.EncryptionContext.EncryptionKey;
@@ -2863,8 +2861,8 @@ public class SimpleProducerConsumerTest extends ProducerConsumerBase {
         int batchSize = encryptionCtx.getBatchSize().orElse(0);
 
         ByteBuf payloadBuf = Unpooled.wrappedBuffer(msg.getData());
-        // try to decrypt
-        MessageCrypto crypto = new MessageCrypto("test", false);
+        // try to decrypt use default MessageCryptoBc
+        MessageCrypto crypto = new MessageCryptoBc("test", false);
         Builder metadataBuilder = MessageMetadata.newBuilder();
         org.apache.pulsar.common.api.proto.PulsarApi.EncryptionKeys.Builder encKeyBuilder = EncryptionKeys.newBuilder();
         encKeyBuilder.setKey(encryptionKeyName);
@@ -2879,7 +2877,7 @@ public class SimpleProducerConsumerTest extends ProducerConsumerBase {
         metadataBuilder.addEncryptionKeys(encKey);
         metadataBuilder.setCompression(CompressionCodecProvider.convertToWireProtocol(compressionType));
         metadataBuilder.setUncompressedSize(uncompressedSize);
-        ByteBuf decryptedPayload = crypto.decrypt(metadataBuilder.build(), payloadBuf, reader);
+        ByteBuf decryptedPayload = crypto.decrypt(() -> metadataBuilder.build(), payloadBuf, reader);
 
         // try to uncompress
         CompressionCodec codec = CompressionCodecProvider.getCompressionCodec(compressionType);
@@ -3288,7 +3286,7 @@ public class SimpleProducerConsumerTest extends ProducerConsumerBase {
     /**
      * It verifies that message failure successfully releases semaphore and client successfully receives
      * InvalidMessageException.
-     * 
+     *
      * @throws Exception
      */
     @Test
diff --git a/pulsar-client-1x-base/pulsar-client-2x-shaded/pom.xml b/pulsar-client-1x-base/pulsar-client-2x-shaded/pom.xml
index 9a65ea5..11af363 100644
--- a/pulsar-client-1x-base/pulsar-client-2x-shaded/pom.xml
+++ b/pulsar-client-1x-base/pulsar-client-2x-shaded/pom.xml
@@ -39,7 +39,7 @@
       <version>${project.parent.version}</version>
     </dependency>
   </dependencies>
-  
+
   <build>
     <plugins>
        <plugin>
diff --git a/pulsar-client-admin-shaded/pom.xml b/pulsar-client-admin-shaded/pom.xml
index c8d0996..f43b29e 100644
--- a/pulsar-client-admin-shaded/pom.xml
+++ b/pulsar-client-admin-shaded/pom.xml
@@ -93,6 +93,8 @@
                   <include>org.yaml:snakeyaml</include>
                   <include>io.swagger:*</include>
                   <include>org.apache.bookkeeper:bookkeeper-common-allocator</include>
+                  <!-- bouncycastle Provider dependencies-->
+                  <include>org.bouncycastle:*</include>
                 </includes>
               </artifactSet>
               <filters>
diff --git a/pulsar-client-all/pom.xml b/pulsar-client-all/pom.xml
index c220fc0..025c7f6 100644
--- a/pulsar-client-all/pom.xml
+++ b/pulsar-client-all/pom.xml
@@ -43,6 +43,12 @@
       <artifactId>pulsar-client-admin-original</artifactId>
       <version>${project.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.apache.pulsar</groupId>
+      <artifactId>pulsar-client-messagecrypto-bc</artifactId>
+      <version>${project.parent.version}</version>
+      <optional>true</optional>
+    </dependency>
   </dependencies>
 
   <build>
@@ -150,6 +156,9 @@
                   <include>org.apache.commons:commons-compress</include>
                   <include>org.tukaani:xz</include>
                   <include>org.apache.bookkeeper:bookkeeper-common-allocator</include>
+                  <!-- bouncycastle Provider dependencies-->
+                  <include>org.bouncycastle:*</include>
+                  <include>org.apache.pulsar:pulsar-client-messagecrypto-bc</include>
                 </includes>
               </artifactSet>
               <filters>
diff --git a/pulsar-client-api/pom.xml b/pulsar-client-api/pom.xml
index 6b26918..e6c84d6 100644
--- a/pulsar-client-api/pom.xml
+++ b/pulsar-client-api/pom.xml
@@ -44,6 +44,13 @@
             <artifactId>pulsar-transaction-common</artifactId>
             <version>${project.version}</version>
         </dependency>
+
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-buffer</artifactId>
+            <version>${netty.version}</version>
+            <scope>provided</scope>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/pulsar-client-api/src/main/java/org/apache/pulsar/client/api/ConsumerBuilder.java b/pulsar-client-api/src/main/java/org/apache/pulsar/client/api/ConsumerBuilder.java
index ed1ba88..1e467fb 100644
--- a/pulsar-client-api/src/main/java/org/apache/pulsar/client/api/ConsumerBuilder.java
+++ b/pulsar-client-api/src/main/java/org/apache/pulsar/client/api/ConsumerBuilder.java
@@ -267,6 +267,17 @@ public interface ConsumerBuilder<T> extends Cloneable {
     ConsumerBuilder<T> cryptoKeyReader(CryptoKeyReader cryptoKeyReader);
 
     /**
+     * Sets a {@link MessageCrypto}.
+     *
+     * <p>Contains methods to encrypt/decrypt message for End to End Encryption.
+     *
+     * @param messageCrypto
+     *            MessageCrypto object
+     * @return the consumer builder instance
+     */
+    ConsumerBuilder<T> messageCrypto(MessageCrypto messageCrypto);
+
+    /**
      * Sets the ConsumerCryptoFailureAction to the value specified.
      *
      * @param action
diff --git a/pulsar-client-api/src/main/java/org/apache/pulsar/client/api/MessageCrypto.java b/pulsar-client-api/src/main/java/org/apache/pulsar/client/api/MessageCrypto.java
new file mode 100644
index 0000000..4d3b395
--- /dev/null
+++ b/pulsar-client-api/src/main/java/org/apache/pulsar/client/api/MessageCrypto.java
@@ -0,0 +1,81 @@
+/**
+ * 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.client.api;
+
+import io.netty.buffer.ByteBuf;
+import java.util.Set;
+import java.util.function.Supplier;
+import org.apache.pulsar.client.api.PulsarClientException.CryptoException;
+
+/**
+ * Interface that abstracts the method to encrypt/decrypt message for End to End Encryption.
+ */
+public interface MessageCrypto<MetadataT, BuilderT> {
+
+    int IV_LEN = 12;
+
+    /*
+     * Encrypt data key using the public key(s) in the argument. <p> If more than one key name is specified, data key is
+     * encrypted using each of those keys. If the public key is expired or changed, application is responsible to remove
+     * the old key and add the new key <p>
+     *
+     * @param keyNames List of public keys to encrypt data key
+     *
+     * @param keyReader Implementation to read the key values
+     *
+     */
+    void addPublicKeyCipher(Set<String> keyNames, CryptoKeyReader keyReader) throws CryptoException;
+
+
+    /*
+     * Remove a key <p> Remove the key identified by the keyName from the list of keys.<p>
+     *
+     * @param keyName Unique name to identify the key
+     *
+     * @return true if succeeded, false otherwise
+     */
+    boolean removeKeyCipher(String keyName);
+
+    /*
+     * Encrypt the payload using the data key and update message metadata with the keyname & encrypted data key
+     *
+     * @param encKeys One or more public keys to encrypt data key
+     *
+     * @param msgMetadata Message Metadata
+     *
+     * @param payload Message which needs to be encrypted
+     *
+     * @return encryptedData if success
+     */
+    ByteBuf encrypt(Set<String> encKeys, CryptoKeyReader keyReader,
+                    Supplier<BuilderT> messageMetadataBuilderSupplier, ByteBuf payload) throws PulsarClientException;
+
+    /*
+     * Decrypt the payload using the data key. Keys used to encrypt data key can be retrieved from msgMetadata
+     *
+     * @param msgMetadata Message Metadata
+     *
+     * @param payload Message which needs to be decrypted
+     *
+     * @param keyReader KeyReader implementation to retrieve key value
+     *
+     * @return decryptedData if success, null otherwise
+     */
+    ByteBuf decrypt(Supplier<MetadataT> messageMetadataSupplier, ByteBuf payload, CryptoKeyReader keyReader);
+}
diff --git a/pulsar-client-messagecrypto-bc/pom.xml b/pulsar-client-messagecrypto-bc/pom.xml
new file mode 100644
index 0000000..73e1f31
--- /dev/null
+++ b/pulsar-client-messagecrypto-bc/pom.xml
@@ -0,0 +1,51 @@
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.pulsar</groupId>
+    <artifactId>pulsar</artifactId>
+    <version>2.6.0-SNAPSHOT</version>
+    <relativePath>..</relativePath>
+  </parent>
+
+  <artifactId>pulsar-client-messagecrypto-bc</artifactId>
+  <packaging>jar</packaging>
+  <description>Message crypto for End to End encryption with BouncyCastleProvider</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>pulsar-common</artifactId>
+      <version>${project.parent.version}</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.pulsar</groupId>
+      <artifactId>bouncy-castle-bc-shaded</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+
+  </dependencies>
+</project>
diff --git a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/MessageCrypto.java b/pulsar-client-messagecrypto-bc/src/main/java/org/apache/pulsar/client/impl/crypto/MessageCryptoBc.java
similarity index 94%
rename from pulsar-client/src/main/java/org/apache/pulsar/client/impl/MessageCrypto.java
rename to pulsar-client-messagecrypto-bc/src/main/java/org/apache/pulsar/client/impl/crypto/MessageCryptoBc.java
index 258e6ea..c8b4aa0 100644
--- a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/MessageCrypto.java
+++ b/pulsar-client-messagecrypto-bc/src/main/java/org/apache/pulsar/client/impl/crypto/MessageCryptoBc.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.pulsar.client.impl;
+package org.apache.pulsar.client.impl.crypto;
 
 import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
@@ -37,7 +37,6 @@ import java.security.NoSuchProviderException;
 import java.security.PrivateKey;
 import java.security.PublicKey;
 import java.security.SecureRandom;
-import java.security.Security;
 import java.security.spec.InvalidKeySpecException;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -47,6 +46,7 @@ import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.TimeUnit;
 
+import java.util.function.Supplier;
 import javax.crypto.BadPaddingException;
 import javax.crypto.Cipher;
 import javax.crypto.IllegalBlockSizeException;
@@ -57,20 +57,25 @@ import javax.crypto.ShortBufferException;
 import javax.crypto.spec.GCMParameterSpec;
 import javax.crypto.spec.SecretKeySpec;
 
+import lombok.extern.slf4j.Slf4j;
 import org.apache.pulsar.client.api.CryptoKeyReader;
 import org.apache.pulsar.client.api.EncryptionKeyInfo;
+import org.apache.pulsar.client.api.MessageCrypto;
 import org.apache.pulsar.client.api.PulsarClientException;
 import org.apache.pulsar.client.api.PulsarClientException.CryptoException;
 import org.apache.pulsar.common.allocator.PulsarByteBufAllocator;
+import org.apache.pulsar.common.api.proto.PulsarApi;
 import org.apache.pulsar.common.api.proto.PulsarApi.EncryptionKeys;
 import org.apache.pulsar.common.api.proto.PulsarApi.KeyValue;
 import org.apache.pulsar.common.api.proto.PulsarApi.MessageMetadata;
+import org.apache.pulsar.common.api.proto.PulsarApi.MessageMetadata.Builder;
 import org.apache.pulsar.shaded.com.google.protobuf.v241.ByteString;
 import org.bouncycastle.asn1.ASN1ObjectIdentifier;
 import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
 import org.bouncycastle.asn1.x9.ECNamedCurveTable;
 import org.bouncycastle.asn1.x9.X9ECParameters;
+import org.bouncycastle.cert.X509CertificateHolder;
 import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
 import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
@@ -81,10 +86,9 @@ import org.bouncycastle.openssl.PEMException;
 import org.bouncycastle.openssl.PEMKeyPair;
 import org.bouncycastle.openssl.PEMParser;
 import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-public class MessageCrypto {
+@Slf4j
+public class MessageCryptoBc implements MessageCrypto<MessageMetadata, MessageMetadata.Builder> {
 
     private static final String ECDSA = "ECDSA";
     private static final String RSA = "RSA";
@@ -97,8 +101,7 @@ public class MessageCrypto {
 
     private static KeyGenerator keyGenerator;
     private static final int tagLen = 16 * 8;
-    public static final int ivLen = 12;
-    private byte[] iv = new byte[ivLen];
+    private byte[] iv = new byte[IV_LEN];
     private Cipher cipher;
     MessageDigest digest;
     private String logCtx;
@@ -112,8 +115,6 @@ public class MessageCrypto {
 
     static final SecureRandom secureRandom;
     static {
-
-        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
         SecureRandom rand = null;
         try {
             rand = SecureRandom.getInstance("NativePRNGNonBlocking");
@@ -124,10 +125,10 @@ public class MessageCrypto {
         secureRandom = rand;
 
         // Initial seed
-        secureRandom.nextBytes(new byte[ivLen]);
+        secureRandom.nextBytes(new byte[IV_LEN]);
     }
 
-    public MessageCrypto(String logCtx, boolean keyGenNeeded) {
+    public MessageCryptoBc(String logCtx, boolean keyGenNeeded) {
 
         this.logCtx = logCtx;
         encryptedDataKeyMap = new ConcurrentHashMap<String, EncryptionKeyInfo>();
@@ -173,14 +174,14 @@ public class MessageCrypto {
         // Generate data key to encrypt messages
         dataKey = keyGenerator.generateKey();
 
-        iv = new byte[ivLen];
+        iv = new byte[IV_LEN];
     }
 
     private PublicKey loadPublicKey(byte[] keyBytes) throws Exception {
 
         Reader keyReader = new StringReader(new String(keyBytes));
         PublicKey publicKey = null;
-        try (org.bouncycastle.openssl.PEMParser pemReader = new org.bouncycastle.openssl.PEMParser(keyReader)) {
+        try (PEMParser pemReader = new PEMParser(keyReader)) {
             Object pemObj = pemReader.readObject();
             JcaPEMKeyConverter pemConverter = new JcaPEMKeyConverter();
             SubjectPublicKeyInfo keyInfo = null;
@@ -205,8 +206,8 @@ public class MessageCrypto {
                 pemObj = pemReader.readObject();
             }
 
-            if (pemObj instanceof org.bouncycastle.cert.X509CertificateHolder) {
-                keyInfo = ((org.bouncycastle.cert.X509CertificateHolder) pemObj).getSubjectPublicKeyInfo();
+            if (pemObj instanceof X509CertificateHolder) {
+                keyInfo = ((X509CertificateHolder) pemObj).getSubjectPublicKeyInfo();
             } else {
                 keyInfo = (SubjectPublicKeyInfo) pemObj;
             }
@@ -289,6 +290,7 @@ public class MessageCrypto {
      * @param keyReader Implementation to read the key values
      *
      */
+    @Override
     public synchronized void addPublicKeyCipher(Set<String> keyNames, CryptoKeyReader keyReader)
             throws CryptoException {
 
@@ -353,8 +355,7 @@ public class MessageCrypto {
      *
      * @return true if succeeded, false otherwise
      */
-    /*
-     */
+    @Override
     public boolean removeKeyCipher(String keyName) {
 
         if (keyName == null) {
@@ -375,8 +376,11 @@ public class MessageCrypto {
      *
      * @return encryptedData if success
      */
+    @Override
     public synchronized ByteBuf encrypt(Set<String> encKeys, CryptoKeyReader keyReader,
-            MessageMetadata.Builder msgMetadata, ByteBuf payload) throws PulsarClientException {
+                                        Supplier<Builder> messageMetadataBuilderSupplier, ByteBuf payload) throws PulsarClientException {
+
+        Builder msgMetadata = messageMetadataBuilderSupplier.get();
 
         if (encKeys.isEmpty()) {
             return payload;
@@ -499,7 +503,7 @@ public class MessageCrypto {
         return true;
     }
 
-    private ByteBuf decryptData(SecretKey dataKeySecret, MessageMetadata msgMetadata, ByteBuf payload) {
+    private ByteBuf decryptData(SecretKey dataKeySecret, PulsarApi.MessageMetadata msgMetadata, ByteBuf payload) {
 
         // unpack iv and encrypted data
         ByteString ivString = msgMetadata.getEncryptionParam();
@@ -574,8 +578,10 @@ public class MessageCrypto {
      *
      * @return decryptedData if success, null otherwise
      */
-    public ByteBuf decrypt(MessageMetadata msgMetadata, ByteBuf payload, CryptoKeyReader keyReader) {
+    @Override
+    public ByteBuf decrypt(Supplier<MessageMetadata> messageMetadataSupplier, ByteBuf payload, CryptoKeyReader keyReader) {
 
+        MessageMetadata msgMetadata = messageMetadataSupplier.get();
         // If dataKey is present, attempt to decrypt using the existing key
         if (dataKey != null) {
             ByteBuf decryptedData = getKeyAndDecryptData(msgMetadata, payload);
@@ -603,7 +609,4 @@ public class MessageCrypto {
         return getKeyAndDecryptData(msgMetadata, payload);
 
     }
-
-    private static final Logger log = LoggerFactory.getLogger(MessageCrypto.class);
-
 }
diff --git a/pulsar-client-shaded/pom.xml b/pulsar-client-shaded/pom.xml
index 3ef9bf3..2e62b02 100644
--- a/pulsar-client-shaded/pom.xml
+++ b/pulsar-client-shaded/pom.xml
@@ -139,11 +139,23 @@
                   <include>com.thoughtworks.paranamer:paranamer</include>
                   <include>org.apache.commons:commons-compress</include>
                   <include>org.tukaani:xz</include>
-
+                  <!-- bouncycastle Provider dependencies-->
+                  <include>org.bouncycastle:*</include>
+                  <include>org.apache.pulsar:pulsar-client-messagecrypto-bc</include>
                 </includes>
               </artifactSet>
               <filters>
                 <filter>
+                  <!-- Shading signed JARs will fail without
+                      this. http://stackoverflow.com/questions/999489/invalid-signature-file-when-attempting-to-run-a-jar -->
+                  <artifact>*:*</artifact>
+                  <excludes>
+                    <exclude>META-INF/*.SF</exclude>
+                    <exclude>META-INF/*.DSA</exclude>
+                    <exclude>META-INF/*.RSA</exclude>
+                  </excludes>
+                </filter>
+                <filter>
                   <artifact>org.apache.pulsar:pulsar-client-original</artifact>
                   <includes>
                     <include>**</include>
diff --git a/pulsar-client/pom.xml b/pulsar-client/pom.xml
index dca5f4f..0981f46 100644
--- a/pulsar-client/pom.xml
+++ b/pulsar-client/pom.xml
@@ -38,6 +38,7 @@
       <artifactId>pulsar-client-api</artifactId>
       <version>${project.parent.version}</version>
     </dependency>
+
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>pulsar-common</artifactId>
@@ -45,6 +46,19 @@
     </dependency>
 
     <dependency>
+      <groupId>org.apache.pulsar</groupId>
+      <artifactId>bouncy-castle-bc-shaded</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.pulsar</groupId>
+      <artifactId>pulsar-client-messagecrypto-bc</artifactId>
+      <version>${project.parent.version}</version>
+      <optional>true</optional>
+    </dependency>
+
+    <dependency>
       <groupId>io.netty</groupId>
       <artifactId>netty-codec-http</artifactId>
     </dependency>
@@ -83,7 +97,7 @@
       <groupId>com.google.code.gson</groupId>
       <artifactId>gson</artifactId>
     </dependency>
-    
+
     <dependency>
       <groupId>org.apache.httpcomponents</groupId>
       <artifactId>httpclient</artifactId>
@@ -131,8 +145,8 @@
       <groupId>net.jcip</groupId>
       <artifactId>jcip-annotations</artifactId>
     </dependency>
-    
-    <!-- httpclient-hostname-verification depends on below dependencies  --> 
+
+    <!-- httpclient-hostname-verification depends on below dependencies  -->
     <dependency>
       <groupId>commons-logging</groupId>
       <artifactId>commons-logging</artifactId>
@@ -157,7 +171,7 @@
       <artifactId>jsonassert</artifactId>
       <version>${skyscreamer.version}</version>
       <scope>test</scope>
-    </dependency> 
+    </dependency>
   </dependencies>
 
   <build>
diff --git a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/ConsumerBuilderImpl.java b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/ConsumerBuilderImpl.java
index e31cc84..111aaea 100644
--- a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/ConsumerBuilderImpl.java
+++ b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/ConsumerBuilderImpl.java
@@ -41,6 +41,7 @@ import org.apache.pulsar.client.api.ConsumerInterceptor;
 import org.apache.pulsar.client.api.CryptoKeyReader;
 import org.apache.pulsar.client.api.DeadLetterPolicy;
 import org.apache.pulsar.client.api.KeySharedPolicy;
+import org.apache.pulsar.client.api.MessageCrypto;
 import org.apache.pulsar.client.api.MessageListener;
 import org.apache.pulsar.client.api.PulsarClientException;
 import org.apache.pulsar.client.api.RegexSubscriptionMode;
@@ -218,6 +219,12 @@ public class ConsumerBuilderImpl<T> implements ConsumerBuilder<T> {
     }
 
     @Override
+    public ConsumerBuilder<T> messageCrypto(@NonNull MessageCrypto messageCrypto) {
+        conf.setMessageCrypto(messageCrypto);
+        return this;
+    }
+
+    @Override
     public ConsumerBuilder<T> cryptoFailureAction(@NonNull ConsumerCryptoFailureAction action) {
         conf.setCryptoFailureAction(action);
         return this;
diff --git a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/ConsumerImpl.java b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/ConsumerImpl.java
index 487c3e4..5c59bca 100644
--- a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/ConsumerImpl.java
+++ b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/ConsumerImpl.java
@@ -58,6 +58,7 @@ import org.apache.pulsar.client.api.ConsumerCryptoFailureAction;
 import org.apache.pulsar.client.api.ConsumerStats;
 import org.apache.pulsar.client.api.DeadLetterPolicy;
 import org.apache.pulsar.client.api.Message;
+import org.apache.pulsar.client.api.MessageCrypto;
 import org.apache.pulsar.client.api.MessageId;
 import org.apache.pulsar.client.api.Messages;
 import org.apache.pulsar.client.api.Producer;
@@ -68,6 +69,7 @@ import org.apache.pulsar.client.api.SubscriptionMode;
 import org.apache.pulsar.client.api.SubscriptionType;
 import org.apache.pulsar.client.api.PulsarClientException.TopicDoesNotExistException;
 import org.apache.pulsar.client.impl.conf.ConsumerConfigurationData;
+import org.apache.pulsar.client.impl.crypto.MessageCryptoBc;
 import org.apache.pulsar.client.impl.transaction.TransactionImpl;
 import org.apache.pulsar.common.protocol.Commands;
 import org.apache.pulsar.common.api.EncryptionContext;
@@ -223,7 +225,21 @@ public class ConsumerImpl<T> extends ConsumerBase<T> implements ConnectionHandle
 
         // Create msgCrypto if not created already
         if (conf.getCryptoKeyReader() != null) {
-            this.msgCrypto = new MessageCrypto(String.format("[%s] [%s]", topic, subscription), false);
+            if (conf.getMessageCrypto() != null) {
+                this.msgCrypto = conf.getMessageCrypto();
+            } else {
+                // default to use MessageCryptoBc;
+                MessageCrypto msgCryptoBc;
+                try {
+                    msgCryptoBc = new MessageCryptoBc(
+                            String.format("[%s] [%s]", topic, subscription),
+                            false);
+                } catch (Exception e) {
+                    log.error("MessageCryptoBc may not included in the jar. e:", e);
+                    msgCryptoBc = null;
+                }
+                this.msgCrypto = msgCryptoBc;
+            }
         } else {
             this.msgCrypto = null;
         }
@@ -1216,7 +1232,7 @@ public class ConsumerImpl<T> extends ConsumerBase<T> implements ConnectionHandle
             }
         }
 
-        ByteBuf decryptedData = this.msgCrypto.decrypt(msgMetadata, payload, conf.getCryptoKeyReader());
+        ByteBuf decryptedData = this.msgCrypto.decrypt(() -> msgMetadata, payload, conf.getCryptoKeyReader());
         if (decryptedData != null) {
             return decryptedData;
         }
@@ -1760,7 +1776,7 @@ public class ConsumerImpl<T> extends ConsumerBase<T> implements ConnectionHandle
                                                     ? e.getMetadataList().stream().collect(
                                                             Collectors.toMap(KeyValue::getKey, KeyValue::getValue))
                                                     : null)));
-            byte[] encParam = new byte[MessageCrypto.ivLen];
+            byte[] encParam = new byte[MessageCrypto.IV_LEN];
             msgMetadata.getEncryptionParam().copyTo(encParam, 0);
             Optional<Integer> batchSize = Optional
                     .ofNullable(msgMetadata.hasNumMessagesInBatch() ? msgMetadata.getNumMessagesInBatch() : null);
diff --git a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/ProducerImpl.java b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/ProducerImpl.java
index 977a7b2..6585842 100644
--- a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/ProducerImpl.java
+++ b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/ProducerImpl.java
@@ -32,7 +32,6 @@ import static org.apache.pulsar.common.protocol.Commands.readChecksum;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.Queues;
-
 import io.netty.buffer.ByteBuf;
 import io.netty.util.Recycler;
 import io.netty.util.Recycler.Handle;
@@ -40,7 +39,6 @@ import io.netty.util.ReferenceCountUtil;
 import io.netty.util.Timeout;
 import io.netty.util.TimerTask;
 import io.netty.util.concurrent.ScheduledFuture;
-
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -53,11 +51,11 @@ import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLongFieldUpdater;
-
 import org.apache.commons.lang3.StringUtils;
 import org.apache.pulsar.client.api.BatcherBuilder;
 import org.apache.pulsar.client.api.CompressionType;
 import org.apache.pulsar.client.api.Message;
+import org.apache.pulsar.client.api.MessageCrypto;
 import org.apache.pulsar.client.api.MessageId;
 import org.apache.pulsar.client.api.Producer;
 import org.apache.pulsar.client.api.ProducerCryptoFailureAction;
@@ -65,6 +63,7 @@ import org.apache.pulsar.client.api.PulsarClientException;
 import org.apache.pulsar.client.api.PulsarClientException.CryptoException;
 import org.apache.pulsar.client.api.Schema;
 import org.apache.pulsar.client.impl.conf.ProducerConfigurationData;
+import org.apache.pulsar.client.impl.crypto.MessageCryptoBc;
 import org.apache.pulsar.client.impl.schema.JSONSchema;
 import org.apache.pulsar.common.api.proto.PulsarApi.MessageMetadata;
 import org.apache.pulsar.common.api.proto.PulsarApi.ProtocolVersion;
@@ -120,7 +119,7 @@ public class ProducerImpl<T> extends ProducerBase<T> implements TimerTask, Conne
     protected volatile long lastSequenceIdPushed;
     private volatile boolean isLastSequenceIdPotentialDuplicated;
 
-    private MessageCrypto msgCrypto = null;
+    private final MessageCrypto msgCrypto;
 
     private ScheduledFuture<?> keyGeneratorTask = null;
 
@@ -163,8 +162,25 @@ public class ProducerImpl<T> extends ProducerBase<T> implements TimerTask, Conne
 
         if (conf.isEncryptionEnabled()) {
             String logCtx = "[" + topic + "] [" + producerName + "] [" + producerId + "]";
-            this.msgCrypto = new MessageCrypto(logCtx, true);
 
+            if (conf.getMessageCrypto() != null) {
+                this.msgCrypto = conf.getMessageCrypto();
+            } else {
+                // default to use MessageCryptoBc;
+                MessageCrypto msgCryptoBc;
+                try {
+                    msgCryptoBc = new MessageCryptoBc(logCtx, true);;
+                } catch (Exception e) {
+                    log.error("MessageCryptoBc may not included in the jar in Producer. e:", e);
+                    msgCryptoBc = null;
+                }
+                this.msgCrypto = msgCryptoBc;
+            }
+        } else {
+            this.msgCrypto = null;
+        }
+
+        if (this.msgCrypto != null) {
             // Regenerate data key cipher at fixed interval
             keyGeneratorTask = client.eventLoopGroup().scheduleWithFixedDelay(() -> {
                 try {
@@ -173,12 +189,13 @@ public class ProducerImpl<T> extends ProducerBase<T> implements TimerTask, Conne
                     if (!producerCreatedFuture.isDone()) {
                         log.warn("[{}] [{}] [{}] Failed to add public key cipher.", topic, producerName, producerId);
                         producerCreatedFuture.completeExceptionally(
-                            PulsarClientException.wrap(e, String.format("The producer %s of the topic %s " +
-                                "adds the public key cipher was failed", producerName, topic)));
+                                PulsarClientException.wrap(e,
+                                        String.format("The producer %s of the topic %s " +
+                                                      "adds the public key cipher was failed",
+                                                producerName, topic)));
                     }
                 }
             }, 0L, 4L, TimeUnit.HOURS);
-
         }
 
         if (conf.getSendTimeoutMs() > 0) {
@@ -552,7 +569,7 @@ public class ProducerImpl<T> extends ProducerBase<T> implements TimerTask, Conne
             return encryptedPayload;
         }
         try {
-            encryptedPayload = msgCrypto.encrypt(conf.getEncryptionKeys(), conf.getCryptoKeyReader(), msgMetadata,
+            encryptedPayload = msgCrypto.encrypt(conf.getEncryptionKeys(), conf.getCryptoKeyReader(), () -> msgMetadata,
                     compressedPayload);
         } catch (PulsarClientException e) {
             // Unless config is set to explicitly publish un-encrypted message upon failure, fail the request
diff --git a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/AuthenticationTls.java b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/AuthenticationTls.java
index a28e354..d75e491 100644
--- a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/AuthenticationTls.java
+++ b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/AuthenticationTls.java
@@ -19,7 +19,6 @@
 package org.apache.pulsar.client.impl.auth;
 
 import java.io.IOException;
-import java.security.Security;
 import java.util.Map;
 
 import org.apache.pulsar.client.api.Authentication;
@@ -44,14 +43,9 @@ public class AuthenticationTls implements Authentication, EncodedAuthenticationP
     private String certFilePath;
     private String keyFilePath;
 
-    // Load Bouncy Castle
-    static {
-        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
-    }
-    
     public AuthenticationTls() {
     }
-    
+
     public AuthenticationTls(String certFilePath, String keyFilePath) {
         this.certFilePath = certFilePath;
         this.keyFilePath = keyFilePath;
@@ -105,7 +99,7 @@ public class AuthenticationTls implements Authentication, EncodedAuthenticationP
         certFilePath = authParams.get("tlsCertFile");
         keyFilePath = authParams.get("tlsKeyFile");
     }
-    
+
     @VisibleForTesting
     public String getCertFilePath() {
         return certFilePath;
diff --git a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/conf/ConsumerConfigurationData.java b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/conf/ConsumerConfigurationData.java
index e64db72..bc93bf2 100644
--- a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/conf/ConsumerConfigurationData.java
+++ b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/conf/ConsumerConfigurationData.java
@@ -40,6 +40,7 @@ import org.apache.pulsar.client.api.ConsumerEventListener;
 import org.apache.pulsar.client.api.CryptoKeyReader;
 import org.apache.pulsar.client.api.DeadLetterPolicy;
 import org.apache.pulsar.client.api.KeySharedPolicy;
+import org.apache.pulsar.client.api.MessageCrypto;
 import org.apache.pulsar.client.api.MessageListener;
 import org.apache.pulsar.client.api.RegexSubscriptionMode;
 import org.apache.pulsar.client.api.SubscriptionInitialPosition;
@@ -87,6 +88,9 @@ public class ConsumerConfigurationData<T> implements Serializable, Cloneable {
     @JsonIgnore
     private CryptoKeyReader cryptoKeyReader = null;
 
+    @JsonIgnore
+    private MessageCrypto messageCrypto = null;
+
     private ConsumerCryptoFailureAction cryptoFailureAction = ConsumerCryptoFailureAction.FAIL;
 
     private SortedMap<String, String> properties = new TreeMap<>();
diff --git a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/conf/ProducerConfigurationData.java b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/conf/ProducerConfigurationData.java
index 654c15f..b6a0763 100644
--- a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/conf/ProducerConfigurationData.java
+++ b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/conf/ProducerConfigurationData.java
@@ -32,6 +32,7 @@ import org.apache.pulsar.client.api.BatcherBuilder;
 import org.apache.pulsar.client.api.CompressionType;
 import org.apache.pulsar.client.api.CryptoKeyReader;
 import org.apache.pulsar.client.api.HashingScheme;
+import org.apache.pulsar.client.api.MessageCrypto;
 import org.apache.pulsar.client.api.MessageRouter;
 import org.apache.pulsar.client.api.MessageRoutingMode;
 import org.apache.pulsar.client.api.ProducerCryptoFailureAction;
@@ -81,6 +82,9 @@ public class ProducerConfigurationData implements Serializable, Cloneable {
     private CryptoKeyReader cryptoKeyReader;
 
     @JsonIgnore
+    private MessageCrypto messageCrypto = null;
+
+    @JsonIgnore
     private Set<String> encryptionKeys = new TreeSet<>();
 
     private CompressionType compressionType = CompressionType.NONE;
diff --git a/pulsar-common/pom.xml b/pulsar-common/pom.xml
index 604941f..9208cfe 100644
--- a/pulsar-common/pom.xml
+++ b/pulsar-common/pom.xml
@@ -111,11 +111,6 @@
     </dependency>
 
     <dependency>
-      <groupId>org.bouncycastle</groupId>
-      <artifactId>bcpkix-jdk15on</artifactId>
-    </dependency>
-
-    <dependency>
       <groupId>org.apache.bookkeeper</groupId>
       <artifactId>circe-checksum</artifactId>
       <version>${bookkeeper.version}</version>
diff --git a/pulsar-common/src/main/java/org/apache/pulsar/common/util/BCLoader.java b/pulsar-common/src/main/java/org/apache/pulsar/common/util/BCLoader.java
new file mode 100644
index 0000000..63f075d
--- /dev/null
+++ b/pulsar-common/src/main/java/org/apache/pulsar/common/util/BCLoader.java
@@ -0,0 +1,28 @@
+/**
+ * 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.common.util;
+
+import java.security.Provider;
+
+/**
+ * This interface declares a Bouncy Castle provider Loader.
+ */
+public interface BCLoader {
+    Provider getProvider();
+}
diff --git a/pulsar-common/src/main/java/org/apache/pulsar/common/util/BcNarDefinition.java b/pulsar-common/src/main/java/org/apache/pulsar/common/util/BcNarDefinition.java
new file mode 100644
index 0000000..650c894
--- /dev/null
+++ b/pulsar-common/src/main/java/org/apache/pulsar/common/util/BcNarDefinition.java
@@ -0,0 +1,47 @@
+/**
+ * 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.common.util;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * Definition of a Bouncy Castle provider loader NAR package.
+ */
+@Data
+@NoArgsConstructor
+public class BcNarDefinition {
+
+    /**
+     * The name of the Bouncy Castle provider type.
+     *   BC/BCFIPS
+     */
+    private String name;
+
+    /**
+     * Description to be used for user help.
+     */
+    private String description;
+
+    /**
+     * The class name for the Bouncy Castle provider loader impl.
+     */
+    private String bcLoaderClass;
+
+}
diff --git a/pulsar-common/src/main/java/org/apache/pulsar/common/util/SearchBcNarUtils.java b/pulsar-common/src/main/java/org/apache/pulsar/common/util/SearchBcNarUtils.java
new file mode 100644
index 0000000..e3d4f88
--- /dev/null
+++ b/pulsar-common/src/main/java/org/apache/pulsar/common/util/SearchBcNarUtils.java
@@ -0,0 +1,116 @@
+/**
+ * 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.common.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.Provider;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.concurrent.CompletableFuture;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.pulsar.common.nar.NarClassLoader;
+
+/**
+ * Utils to load one Bouncy Castle Provider.
+ *  Prefered:   `org.bouncycastle.jce.provider.BouncyCastleProvider`
+ *  or:         `org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider`.
+ */
+@Slf4j
+public class SearchBcNarUtils {
+    private static final String BC_DEF_NAME = "bouncy-castle.yaml";
+
+    /**
+     * Extract the Bouncy Castle Provider class from a archive path.
+     * Search the path, and should only have 1 nar in the path.
+     *
+     * @param loaderDirectory nar package path
+     * @return the Bouncy Castle Provider class name
+     * @throws IOException when fail to retrieve the pulsar offloader class
+     */
+    static Provider getBcProvider(String loaderDirectory) throws IOException {
+        Path path = Paths.get(loaderDirectory).toAbsolutePath();
+        log.info("Searching for Bouncy Castle Loader in {}", path);
+        if (!path.toFile().exists()) {
+            log.warn("Bouncy Castle Loader archive directory not found");
+            return null;
+        }
+
+        try (DirectoryStream<Path> stream = Files.newDirectoryStream(path, "*.nar")) {
+            try {
+                Iterator<Path> iterator = stream.iterator();
+                String narPath = iterator.next().toString();
+
+                NarClassLoader ncl = NarClassLoader.getFromArchive(
+                        new File(narPath),
+                        Collections.emptySet(),
+                        BCLoader.class.getClassLoader());
+                String configStr = ncl.getServiceDefinition(BC_DEF_NAME);
+
+                BcNarDefinition nar = ObjectMapperFactory.getThreadLocalYaml()
+                        .readValue(configStr, BcNarDefinition.class);
+
+                if (StringUtils.isEmpty(nar.getBcLoaderClass())) {
+                    throw new IOException(
+                            String.format("The '%s' not provided a Bouncy Castle Loader in nar yaml file",
+                                    nar.getName()));
+                }
+
+                Class loaderClass = ncl.loadClass(nar.getBcLoaderClass());
+                CompletableFuture<Provider> loadFuture = new CompletableFuture<>();
+                Thread loadingThread = new Thread(() -> {
+                    Thread.currentThread().setContextClassLoader(ncl);
+                    try {
+                        Object loader = loaderClass.newInstance();
+                        if (!(loader instanceof BCLoader)) {
+                            throw new IOException("Class " + nar.getBcLoaderClass() + " not a impl of "
+                                                  + BCLoader.class.getName());
+                        }
+
+                        Provider provider = ((BCLoader) loader).getProvider();
+                        log.info("Found Bouncy Castle loader {} from {}, provider: {}",
+                                loader.getClass().getCanonicalName(), path, provider.getName());
+                        loadFuture.complete(provider);
+                    } catch (Throwable t) {
+                        log.error("Failed to load Bouncy Castle Provider ", t);
+                        loadFuture.completeExceptionally(t);
+                    }
+                }, "load-factory-" + loaderClass);
+                try {
+                    loadingThread.start();
+                    Provider ret = loadFuture.get();
+                    if (iterator.hasNext()) {
+                        throw new RuntimeException("Should only have 1 Bouncy Castle Provider nar provided");
+                    }
+                    return ret;
+                } finally {
+                    loadingThread.join();
+                }
+            } catch (Throwable t) {
+                log.error("Failed to load Bouncy Castle Provider with error", t);
+                throw new RuntimeException(t);
+            }
+        }
+    }
+}
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 f77743f..d3a2615 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
@@ -35,7 +35,9 @@ import java.security.KeyStore;
 import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
+import java.security.Provider;
 import java.security.SecureRandom;
+import java.security.Security;
 import java.security.UnrecoverableKeyException;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateFactory;
@@ -51,16 +53,80 @@ import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLException;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.TrustManagerFactory;
+import lombok.extern.slf4j.Slf4j;
 import org.eclipse.jetty.util.ssl.SslContextFactory;
 
 /**
  * Helper class for the security domain.
  */
+@Slf4j
 public class SecurityUtility {
 
-    static {
-        // Fixes loading PKCS8Key file: https://stackoverflow.com/a/18912362
-        java.security.Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
+    public static final Provider BC_PROVIDER = getProvider();
+    public static final String BC_FIPS_PROVIDER_CLASS = "org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider";
+    public static final String BC_NON_FIPS_PROVIDER_CLASS = "org.bouncycastle.jce.provider.BouncyCastleProvider";
+    // Security.getProvider("BC") / Security.getProvider("BCFIPS").
+    // also used to get Factories. e.g. CertificateFactory.getInstance("X.509", "BCFIPS")
+    public static final String BC_FIPS = "BCFIPS";
+    public static final String BC = "BC";
+
+    public static boolean isBCFIPS() {
+        return BC_PROVIDER.getClass().getCanonicalName().equals(BC_FIPS_PROVIDER_CLASS);
+    }
+
+    /**
+     * Get Bouncy Castle provider, and call Security.addProvider(provider) if success.
+     *  1. try get from classpath.
+     *  2. try get from Nar.
+     */
+    public static Provider getProvider() {
+        boolean isProviderInstalled =
+                Security.getProvider(BC) != null || Security.getProvider(BC_FIPS) != null;
+
+        if (isProviderInstalled) {
+            Provider provider = Security.getProvider(BC) != null
+                    ? Security.getProvider(BC)
+                    : Security.getProvider(BC_FIPS);
+            log.info("Already instantiated Bouncy Castle provider {}", provider.getName());
+            return provider;
+        }
+
+        // Not installed, try load from class path
+        try {
+            return getBCProviderFromClassPath();
+        } catch (Exception e) {
+            log.warn("Not able to get Bouncy Castle provider for both FIPS and Non-FIPS from class path:", e);
+        }
+
+        // failed to get from class path. try to get from Nar file.
+        try {
+            // User need set the bc nar path in java env.
+            return SearchBcNarUtils.getBcProvider(System.getProperty("BcPath"));
+        } catch (IOException ioe) {
+            throw new RuntimeException(ioe);
+        }
+    }
+
+    /**
+     * Get Bouncy Castle provider from classpath, and call Security.addProvider.
+     * Throw Exception if failed.
+     */
+    public static Provider getBCProviderFromClassPath() throws Exception {
+        Class clazz;
+        try {
+            // prefer non FIPS, for backward compatibility concern.
+            clazz = Class.forName(BC_NON_FIPS_PROVIDER_CLASS);
+        } catch (ClassNotFoundException cnf) {
+            log.warn("Not able to get Bouncy Castle provider: {}, try to get FIPS provider {}",
+                    BC_NON_FIPS_PROVIDER_CLASS, BC_FIPS_PROVIDER_CLASS);
+            // attempt to use the FIPS provider.
+            clazz = Class.forName(BC_FIPS_PROVIDER_CLASS);
+        }
+
+        Provider provider = (Provider) clazz.newInstance();
+        Security.addProvider(provider);
+        log.info("Found and Instantiated Bouncy Castle provider in classpath {}", provider.getName());
+        return provider;
     }
 
     public static SSLContext createSslContext(boolean allowInsecureConnection, Certificate[] trustCertificates)
diff --git a/pulsar-discovery-service/pom.xml b/pulsar-discovery-service/pom.xml
index 9cb1627..33ea4b3 100644
--- a/pulsar-discovery-service/pom.xml
+++ b/pulsar-discovery-service/pom.xml
@@ -63,6 +63,12 @@
     </dependency>
 
     <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>bouncy-castle-bc-shaded</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
       <groupId>org.eclipse.jetty</groupId>
       <artifactId>jetty-server</artifactId>
     </dependency>
@@ -111,12 +117,12 @@
       <groupId>io.swagger</groupId>
       <artifactId>swagger-annotations</artifactId>
     </dependency>
-    
+
     <dependency>
       <groupId>org.glassfish.jersey.inject</groupId>
       <artifactId>jersey-hk2</artifactId>
     </dependency>
-    
+
     <dependency>
       <groupId>javax.xml.bind</groupId>
       <artifactId>jaxb-api</artifactId>
diff --git a/pulsar-functions/worker/pom.xml b/pulsar-functions/worker/pom.xml
index 2a0082e..7df5edd 100644
--- a/pulsar-functions/worker/pom.xml
+++ b/pulsar-functions/worker/pom.xml
@@ -44,6 +44,21 @@
       <groupId>${project.groupId}</groupId>
       <artifactId>pulsar-functions-runtime</artifactId>
       <version>${project.version}</version>
+      <exclusions>
+        <!-- bouncy-castle-bc-shaded that contains in pulsar-client-original already contains this-->
+        <exclusion>
+          <groupId>org.bouncycastle</groupId>
+          <artifactId>bcpkix-jdk15on</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.bouncycastle</groupId>
+          <artifactId>bcprov-jdk15on</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.bouncycastle</groupId>
+          <artifactId>bcprov-ext-jdk15on</artifactId>
+        </exclusion>
+      </exclusions>
     </dependency>
 
     <dependency>
diff --git a/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/ProxyServiceStarter.java b/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/ProxyServiceStarter.java
index f9af23a..df0e064 100644
--- a/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/ProxyServiceStarter.java
+++ b/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/ProxyServiceStarter.java
@@ -34,7 +34,6 @@ import org.slf4j.LoggerFactory;
 
 import com.beust.jcommander.JCommander;
 import com.beust.jcommander.Parameter;
-import com.google.common.collect.Maps;
 
 import io.netty.util.internal.PlatformDependent;
 import io.prometheus.client.CollectorRegistry;
@@ -126,8 +125,6 @@ public class ProxyServiceStarter {
             checkArgument(!isEmpty(config.getZookeeperServers()), "zookeeperServers must be provided");
         }
 
-        java.security.Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
-
         AuthenticationService authenticationService = new AuthenticationService(
                 PulsarConfigurationLoader.convertFrom(config));
         // create proxy service
diff --git a/pulsar-sql/presto-distribution/LICENSE b/pulsar-sql/presto-distribution/LICENSE
index e1d08d1..1739f77 100644
--- a/pulsar-sql/presto-distribution/LICENSE
+++ b/pulsar-sql/presto-distribution/LICENSE
@@ -546,11 +546,10 @@ Public Domain (CC0) -- licenses/LICENSE-CC0.txt
  * Reactive Streams
     - reactive-streams-1.0.2.jar
 
-Bouncy Castle License
- * Bouncy Castle -- licenses/LICENSE-bouncycastle.txt
-    - bcpkix-jdk15on-1.60.jar
-    - bcprov-jdk15on-1.60.jar
-
 Creative Commons Attribution License
  * Jcip -- licenses/LICENSE-jcip.txt
     - jcip-annotations-1.0.jar
+
+Bouncy Castle License
+ * Bouncy Castle -- licenses/LICENSE-bouncycastle.txt
+    - bouncy-castle-bc-shaded-2.6.0-SNAPSHOT.jar
diff --git a/pulsar-testclient/pom.xml b/pulsar-testclient/pom.xml
index f7098da..38d0654 100644
--- a/pulsar-testclient/pom.xml
+++ b/pulsar-testclient/pom.xml
@@ -61,6 +61,12 @@
 
 		<dependency>
 			<groupId>${project.groupId}</groupId>
+			<artifactId>pulsar-client-messagecrypto-bc</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>${project.groupId}</groupId>
 			<artifactId>pulsar-broker</artifactId>
 			<version>${project.version}</version>
 		</dependency>
diff --git a/site2/docs/security-bouncy-castle.md b/site2/docs/security-bouncy-castle.md
new file mode 100644
index 0000000..e2d2a5d
--- /dev/null
+++ b/site2/docs/security-bouncy-castle.md
@@ -0,0 +1,121 @@
+---
+id: security-bouncy-castle
+title: Bouncy Castle Providers
+sidebar_label: Bouncy Castle Providers
+---
+
+## BouncyCastle Introduce
+
+`Bouncy Castle` is a Java library that complements the default Java Cryptographic Extension (JCE), 
+and it many more cipher suites and algorithms than the default JCE provided by Sun.
+
+In addition to that, `Bouncy Castle` has lots of utilities for reading arcane formats like PEM and ASN.1 that no sane person would want to rewrite themselves.
+
+In Pulsar, security and crypto have dependencies on BouncyCastle Jars. For the detailed installing and configuring Bouncy Castle FIPS, see [BC FIPS Documentation](https://www.bouncycastle.org/documentation.html), especially the **User Guides** and **Security Policy** PDFs.
+
+`Bouncy Castle` provides both [FIPS](https://www.bouncycastle.org/fips_faq.html) and non-FIPS version. But in a JVM, you can not include both of the 2 versions, and you need to exclude the current version before include the other.
+
+In Pulsar, the security and crypto methods also depends on `Bouncy Castle`, especially in [TLS Authentication](security-tls-authentication.md) and [Transport Encryption](security-encryption.md). This document contains the configuration between BouncyCastle FIPS(BC-FIPS) and non-FIPS(BC-non-FIPS) version while using Pulsar.
+
+## Include dependencies of BC-non-FIPS
+
+By default, BouncyCastle non-FIPS version is build along with Pulsar's Broker and Java client.
+
+Pulsar module `bouncy-castle-bc`, which defined by `bouncy-castle/bc/pom.xml` contains the needed non-FIPS jars for Pulsar.
+
+```xml
+    <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bcpkix-jdk15on</artifactId>
+      <version>${bouncycastle.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bcprov-ext-jdk15on</artifactId>
+      <version>${bouncycastle.version}</version>
+    </dependency>
+```
+
+And based on Pulsar module `bouncy-castle-bc`, Pulsar shades a fat jar in module `bouncy-castle-bc-shaded` that contains needed classes of BouncyCastle non-FIPS jars.
+By using this `bouncy-castle-bc-shaded` module, user can easily include and exclude BouncyCastle non-FIPS jars.
+
+### Pulsar Client and Broker dependencies on BC-non-FIPS
+
+Pulsar Client(`pulsar-client-original`) module include BouncyCastle non-FIPS jars by add dependency like this:
+
+```xml
+    <dependency>
+      <groupId>org.apache.pulsar</groupId>
+      <artifactId>bouncy-castle-bc-shaded</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+```
+
+And Pulsar Broker (`pulsar-broker`) module include BouncyCastle non-FIPS jars by indirectly include Pulsar Client(`pulsar-client-original`) module.
+```xml
+    <dependency>
+      <groupId>org.apache.pulsar</groupId>
+      <artifactId>pulsar-client-original</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+```
+
+## Exclude BC-non-FIPS and include BC-FIPS
+
+After understanding the above dependencies, user can easily exclude non-FIPS version and include FIPS version.
+
+### BC-FIPS
+
+Pulsar module `bouncy-castle-bcfips`, which defined by `bouncy-castle/bcfips/pom.xml` contains the needed FIPS jars for Pulsar.
+
+```xml
+    <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bc-fips</artifactId>
+      <version>${bouncycastlefips.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bcpkix-fips</artifactId>
+      <version>${bouncycastlefips.version}</version>
+    </dependency>
+```
+
+User can choose include module `bouncy-castle-bcfips` module directly, or include original BC-FIPS jars. 
+
+For example:
+
+```xml
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>pulsar-broker</artifactId>
+      <version>${project.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>${project.groupId}</groupId>
+          <artifactId>bouncy-castle-bc-shaded</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+
+    <!--exclude bouncy castle non-FIPS version, then load fips version-->
+    <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bc-fips</artifactId>
+      <version>${bouncycastlefips.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bcpkix-fips</artifactId>
+      <version>${bouncycastlefips.version}</version>
+    </dependency>
+``` 
+ 
+Besides this, module `bouncy-castle-bcfips` builds contain an output with format NAR, you can set java environment by `-DBcPath='nar/file/path'`, Pulsar will auto load it.
+
+For more example, you can reference module `bcfips-include-test` and `bcfips-nar-test`.
+
+
diff --git a/site2/docs/security-tls-authentication.md b/site2/docs/security-tls-authentication.md
index 3f8091d..e510ce0 100644
--- a/site2/docs/security-tls-authentication.md
+++ b/site2/docs/security-tls-authentication.md
@@ -8,6 +8,8 @@ sidebar_label: Authentication using TLS
 
 TLS authentication is an extension of [TLS transport encryption](security-tls-transport.md). Not only servers have keys and certs that the client uses to verify the identity of servers, clients also have keys and certs that the server uses to verify the identity of clients. You must have TLS transport encryption configured on your cluster before you can use TLS authentication. This guide assumes you already have TLS transport encryption configured.
 
+`Bouncy Castle Provider` provides TLS related cipher suites and algorithms in Pulsar. If you need [FIPS](https://www.bouncycastle.org/fips_faq.html) version of `Bouncy Castle Provider`, please reference [Bouncy Castle page](security-bouncy-castle.md).
+
 ### Create client certificates
 
 Client certificates are generated using the certificate authority. Server certificates are also generated with the same certificate authority.
diff --git a/site2/docs/security-tls-transport.md b/site2/docs/security-tls-transport.md
index c18fafd..12ede1c 100644
--- a/site2/docs/security-tls-transport.md
+++ b/site2/docs/security-tls-transport.md
@@ -28,6 +28,8 @@ For TLS transport encryption, the clients can use the **trust cert** to verify t
 
 For TLS authentication, the server uses the **trust cert** to verify that the client has a key pair that the certificate authority signed. The common name of the **client cert** is then used as the client's role token (see [Overview](security-overview.md)).
 
+`Bouncy Castle Provider` provides cipher suites and algorithms in Pulsar. If you need [FIPS](https://www.bouncycastle.org/fips_faq.html) version of `Bouncy Castle Provider`, please reference [Bouncy Castle page](security-bouncy-castle.md).
+
 ## Create TLS certificates
 
 Creating TLS certificates for Pulsar involves creating a [certificate authority](#certificate-authority) (CA), [server certificate](#server-certificate), and [client certificate](#client-certificate).
diff --git a/site2/website/sidebars.json b/site2/website/sidebars.json
index 6ebbea4..bee59cc 100644
--- a/site2/website/sidebars.json
+++ b/site2/website/sidebars.json
@@ -74,7 +74,8 @@
       "security-kerberos",
       "security-authorization",
       "security-encryption",
-      "security-extending"
+      "security-extending",
+      "security-bouncy-castle"
     ],
     "Client libraries": [
       "client-libraries-java",