Bouncy Castle Providers
BouncyCastle 介绍
Bouncy Castle
是Java 加密拓展(JCE)的升级版本,相对Sun 提供的默认 JCE,它提供了许多密钥套件与算法。
除此之外,Bouncy Castle
有许多能读取像 PEM 和 ASN.1 这些晦涩格式的工具。这些格式正常人是不会想去自己重写一遍的。
在 Pulsar 中,安全与加密都对 BouncyCastle Jar 包有依赖。 关于Bouncy Castle FIPS的详细安装和配置,请参阅 BC FIPS 文档, 特别是 用户指南 和 安全政策 PDF 文档。
Bouncy Castle
提供 FIPS 与 non-FIPS 两个版本。 但在 JVM 中,不能同时引入两个版本,所以需要先排除当前版本才能引入另一个版本。
在 Pulsar 中,安全和加密方法也依赖于 Bouncy Castle
, 特别是 TLS 认证 和 传输加密。 本文档包含使用 Pulsar 时的 Bounccastle FIPS(BC-FIPS)和 non-FIPS(BC-non-FIPS)版本的配置。
Pulsar 中打包 Bounccastle 模块
对于 Pulsar 中的bouncy-castle
模块,我们提供了2个子模块:bouncy-castle-bc
(针对 non-FIPS 版本)和bouncy-castle-bcfips
(针对 FIPS 版本),将 BC jar 打包在一起,使 Bouncy Castle
的包含和排除更容易。
为了实现这一目的,我们需要将几个 bouncy-castle
jars 一起打包到 bouncy-castle-bc
或 bouncy-castle-bfips
中。 因为每一个原始的 bouncy-castle jar 包都和安全有关,所以 BouncyCastle 为每个 JAR 包都提供了签名。 但是当我们重新打包时,Maven shade 机制引入了 BouncyCastle jar 文件,并将签名放入了 META-INF(这些签名对新的 uber-jar 无效,只适用于原始的 BC jar)。 通常,你会遇到这种报错:java.lang.SecurityException: Invalid signature file digest for Manifest main attributes
你可以在 mvn pom 文件中排除这些签名,以避免上面的错误:
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
但它也可能引入新的加密报错,例如:java.security.NoSuchAlgorithmException: PBEWithSHA256And256BitAES-CBC-BC SecretKeyFactory not available
。可以通过像如下这样显式地指定在哪里找到加密算法:SecretKeyFactory.getInstance("PBEWithSHA256And256BitAES-CBC-BC","BC")
。这样做将会发现真正的报错信息:java.security.NoSuchProviderException: JCE cannot authenticate the provider BC
。
因此,我们需要使用 可执行软件包插件 。它通过 jar-in-jar 方法将 BouncyCastle 的签名在一个单独的、可执行的 jar 包中。
引入 BC-non-FIPS 的依赖
Pulsar 所用的bouncy-castle-bc
模块,定义在bouncy-castle/bc/pom.xml
文件内。它包含了 Pulsar 所需的 non-FIPS JAR包,该 JAR 包是使用 jar-in-jar 的方式打包的(即必须提供<classifier>pkg</classifier>
)。
<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>
通过使用 bouncy-castle-bc
模块,你可以轻松地将 Bouncycastle non-FIPS JAR 包引入或排除。
引入 BC-non-FIPS 模块(bouncy-castle-bc
)
对于 Pulsar 客户端,用户需要使用 bouncy-castle 模块,所以pulsar-client-original
将包含bouncy-castle-bc
模块。并且使用<classifier>pkg</classifier>
设置和jar-in-jar
包的引用关系。 引入依赖示例如下:
<dependency>
<groupId>org.apache.pulsar</groupId>
<artifactId>bouncy-castle-bc</artifactId>
<version>${pulsar.version}</version>
<classifier>pkg</classifier>
</dependency>
默认情况下,pulsar-client-original
包含了bouncy-castle-bc
模块。并且pulsar-client-original
已经包含在许多其他模块中,例如pulsar-client-admin
,pulsar-broker
。
但是因为上面的 shade 包和签名的原因,我们将不会将bouncy-castle
模块打包到pulsar-client-all
的的其他 shade 模块目录中。例如pulsar-client-shaded
, pulsar-client-admin-shaded
和 pulsar-broker-shaded
。 所以,在 shade 模块中,我们将排除 bouncy-castle
模块。
<filters>
<filter>
<artifact>org.apache.pulsar:pulsar-client-original</artifact>
<includes>
<include>**</include>
</includes>
<excludes>
<exclude>org/bouncycastle/**</exclude>
</excludes>
</filter>
</filters>
这意味着,bouncy-castle
相关的 JAR 包不会被放在这些扩展的 Jar 包中。
BC-FIPS 模块 (bouncy-castle-bcfips
)
在 bouncy-castle/bcfips/pom.xml
中定义的 Pulsar 模块 bouncy-castle-bcfips
,包含了Pulsar 所需的 FIPS jar 包。 和 bouncy-castle-bc
类似, bouncy-castle-bfips
也是用 jar-in -jar
方式打包,以便引入/排除包.
<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>
排除 BC-non-FIPS 并引入 BC-FIPS
如果你想要从 BC-non-FIPS 切换到 BC-FIPS 版本,下面是 Pulsar-broker
模块的一个示例:
<dependency>
<groupId>org.apache.pulsar</groupId>
<artifactId>pulsar-broker</artifactId>
<version>${pulsar.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.pulsar</groupId>
<artifactId>bouncy-castle-bc</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.pulsar</groupId>
<artifactId>bouncy-castle-bcfips</artifactId>
<version>${pulsar.version}</version>
<classifier>pkg</classifier>
</dependency>
更多的示例, 您可以参考 bcfips-include-test
模块。