【问题标题】:create an SSLContext instance using a Bouncy Castle provider使用 Bouncy Castle 提供程序创建 SSLContext 实例
【发布时间】:2014-05-28 08:43:37
【问题描述】:

我一直在创建 SSLContext(我想用它来实例化 SSLEngine 以通过 java-nio 处理加密传输):

代码

String protocol = "TLSv1.2";
Provider provider = new BouncyCastleProvider();
Security.addProvider(provider);
sslContext = SSLContext.getInstance(protocol,provider.getName());

抛出以下异常:

Exception in thread "main" java.lang.RuntimeException: java.security.NoSuchAlgorithmException: no such algorithm: SSL for provider BC
at org.bitmash.network.tcp.ssl.SslTransferFactory.<init>(SslTransferFactory.java:43)
at org.bitmash.network.http.HttpsServer.<init>(HttpsServer.java:19)

我将 Bouncy Castle 的当前提供程序包“bcprov-jdk15on-150.jar”(我从 here 获得)附加到应用程序类路径及其引导类路径(通过 VM-Option -Xbootclasspath/p),但是都没有解决问题。我还尝试了 protocol 的不同值(即“SSL”和“TLSv1”),但没有任何效果。

另外,我发现有类似问题的人here 和here。但与他们相比,我的目标是(并且我正在使用)Java 7(或更高版本),但我仍然有这个问题。通常以这种方式使用 Bouncy Castle 是否可行,或者我是否必须使用它们各自的 API 而不是 oracle 的 NIO via SSLEngine 重写我的协议(这是我现在正在做的方式)?

非常感谢您在这里提供的任何帮助。

【问题讨论】:

    标签: java ssl bouncycastle sslengine


    【解决方案1】:

    我知道这是一个老问题,但我需要一个答案(所以我正在创建一个):

    • [是否可以] 使用 Bouncy Castle 提供程序创建 SSLContext 实例 [?]
    • 没有

    为什么不呢?

    调试这行代码:

    Provider [] providers = Security.getProviders();
    
    • 默认的 SunJSSE 1.7 版实现以下 SSLContext 值:

      Alg.Alias.SSLContext.SSL=TLSv1
      Alg.Alias.SSLContext.SSLv3=TLSv1
      SSLContext.Default=sun.security.ssl.SSLContextImpl$DefaultSSLContext
      SSLContext.TLSv1=sun.security.ssl.SSLContextImpl$TLS10Context
      SSLContext.TLSv1.1=sun.security.ssl.SSLContextImpl$TLS11Context
      SSLContext.TLSv1.2=sun.security.ssl.SSLContextImpl$TLS12Context

    • 使用 bcprov-jdk15on-152.jar 并将新的 BouncyCastleProvider() 添加到 Security,可以观察到没有可用的 SSLContext 值。

    这应该是有道理的,因为 Bouncy Castle 是 JCE 实现,而不是 JSSE 实现。

    【讨论】:

    • 另一方面,如果您尝试使用 KeyGenerator 创建密钥,那么 BC 非常适合这样做! KeyGenerator.getInstance("Threefish-256","BC") 或 KeyGenerator.getInstance("HMACSHA512/224","BC") - 你明白了......
    【解决方案2】:

    Bouncy Castle 实际上在 1.56 版中提供了 JSSE 实现。 只需确保在应用程序启动时将其配置为更高的优先级:

    Security.insertProviderAt(new BouncyCastleJsseProvider(), 1);
    

    或者,作为替代,在全局 &lt;JRE_HOME&gt;/lib/security/java.security 文件中:

    security.provider.1=org.bouncycastle.jsse.provider.BouncyCastleJsseProvider
    ...
    security.provider.6=com.sun.net.ssl.internal.ssl.Provider
    

    您可以将它与标准 API 一起使用:

    SSLContext context = SSLContext.getInstance("TLS");
    

    【讨论】:

    • 并注意它是一个单独的 jar - bctls-$version 不是(只是) bcprov-$version 。
    【解决方案3】:

    Bouncy Castle 为 JSSE 实现了两种类型的提供程序:

    • 一个普通 DTLS/TLS 和 JSSE 提供程序包
    • FIPS-compliant (D)TLS API 和 JSSE 提供程序

    可以在此处找到每个提供商的当前文档:ordinary 和 FIPS-compliant。

    这些 JAR 文件与 Bouncy Castle JCE 提供程序的 JAR 文件不同。在撰写本文时,JSSE 提供程序 JAR 文件称为 bctls-jdk15on-1.64.jar 和 bctls-fips-1.0.9.jar,而 JCE 提供程序是 bcprov-jdk15on-1.64.jar。

    这是文档的摘录:

    2.1 BCJSSE Provider 安装到 JRE

    安装 bctls jar 后,如果应用程序全局需要提供程序类 BouncyCastleJsseProvider,则可能需要安装它。

    通过将提供程序定义添加到 JRE/JDK 的 jre/lib/security 目录中的 java.security 文件,可以在 JVM 中静态安装提供程序。

    也可以在执行期间添加提供程序。如果您希望在执行期间将提供程序全局添加到 JVM,您可以将以下导入添加到您的代码中:

    import java.security.Security
    import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider
    

    然后插入一行

    Security.addProvider(new BouncyCastleJsseProvider());
    

    然后可以通过引用名称BCJSSE 来使用提供程序,例如:

    SSLContext clientContext = SSLContext.getInstance("TLS", "BCJSSE");
    

    或者,如果您不希望全局安装提供程序,而是在本地使用它,则可以将提供程序传递给要创建实例的 JSSE 类的 getInstance() 方法。

    例如:

    SSLContext clientContext = SSLContext.getInstance("TLS",
           new BouncyCastleJsseProvider());
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-29
      • 1970-01-01
      • 2021-05-15
      • 2017-12-18
      相关资源
      最近更新 更多