添加 BouncyCastle 提供程序会破坏 KeyStore.load()

2024-03-14

我使用以下命令生成了密钥库:

keytool -genkeypair -keystore test.ks -storetype pkcs12

然后我运行以下测试(base64 代表我创建的密钥库):

private static final String KEYSTORE_BASE64 = "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";

@Test
public void testWithoutBouncyCastle() throws Exception {
    doTest();
}

private void doTest() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException {
    byte[] keyStoreBytes = Base64.getDecoder().decode(KEYSTORE_BASE64);
    KeyStore keystore = KeyStore.getInstance("jks");
    keystore.load(new ByteArrayInputStream(keyStoreBytes), "secret".toCharArray());

    Key key = keystore.getKey("mykey", "secret".toCharArray());
    assertThat(key, is(notNullValue()));
}

测试通过。

现在我做同样的事情,但首先我在位置 2(基于 1)添加 BouncyCastle 提供程序:

@Test
public void testWithBouncyCastle() throws Exception {
    Security.insertProviderAt(new BouncyCastleProvider(), 2);

    doTest();
}

测试失败:

java.io.IOException: keystore password was incorrect

    at sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:2059)
    at sun.security.provider.KeyStoreDelegator.engineLoad(KeyStoreDelegator.java:238)
    at sun.security.provider.JavaKeyStore$DualFormatJKS.engineLoad(JavaKeyStore.java:70)
    at java.security.KeyStore.load(KeyStore.java:1445)
    at PBETest.doTest(PBETest.java:43)
    at PBETest.testWithBouncyCastle(PBETest.java:37)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.security.UnrecoverableKeyException: failed to decrypt safe contents entry: javax.crypto.BadPaddingException: pad block corrupted
    ... 28 more

关于商店类型的一些附注

请注意,密钥库是 PKCS12 存储,我尝试将其加载为 JKS。我必须使用的库也执行相同的操作,因此代码也是如此。另外,JDK 似乎已经准备好了:getInstance("jks") KeyStoreDelegator使用的类首先尝试加载作为 JKS 存储提供的“事物”,然后返回到 PKCS12 路径。

另一个观察结果是getInstance("pkcs12")在两种情况下都能正常工作(没有 BouncyCastle 和有 BouncyCastle)。本例中使用的代码(不是KeyStoreDelegator)与JKS场景的pkcs12相关路径不同,可能是因为它运行成功。

回到主题

当 PKCS12 相关分支尝试使用密钥库密码解密某些内容时,会出现此问题。它首先将密钥库密码转换为 PBE 密钥来实现此目的

private SecretKey getPBEKey(char[] var1) throws IOException {
    SecretKey var2 = null;

    try {
        PBEKeySpec var3 = new PBEKeySpec(var1);
        SecretKeyFactory var4 = SecretKeyFactory.getInstance("PBE");
        var2 = var4.generateSecret(var3);
        var3.clearPassword();
        return var2;
    } catch (Exception var5) {
        throw new IOException("getSecretKey failed: " + var5.getMessage(), var5);
    }
}

然后使用该密钥(以及算法参数)进行解密:

SecretKey key = this.getPBEKey(var2);
Cipher cipher = Cipher.getInstance(var27.toString());
cipher.init(2, key, var28);
var38 = cipher.doFinal(var38);

抱歉,变量名太糟糕了,这就是 IDE 给我的。var2 is a char[]代表密钥库密码,var27.toString()给出“1.2.840.113549.1.12.1.6”,var28包含算法参数。

doFinal()是失败的调用。

在“没有BC”的情况下,Cipher实例来自 SunJCE 提供商(并且工作正常);在“与 BC”场景中,CipherBC提供的实例失败。

以下是 BouncyCastle 安装后的提供商列表:

SUN
BC
SunRsaSign
SunEC
SunJSSE
SunJCE
SunJGSS
SunSASL
XMLDSig
SunPCSC

所以 BC 在 SunJCE 之前,因此它赢得了比赛并提供了Cipher.

不幸的是,几乎不可能避免“将 PKCS12 加载为 JKS”的行为;另外,我想避免将 BouncyCastle 提供程序移至提供程序列表的末尾,因为这可能会破坏其他一些代码。

问题是:

  1. 这是 BouncyCastle 中的错误吗?
  2. 有什么办法可以解决这个问题吗?

Java是Oracle JDK 1.8.0_161,BouncyCastle版本是1.54(我也尝试过1.57,这似乎是最新版本,但我得到了相同的结果)。


None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

添加 BouncyCastle 提供程序会破坏 KeyStore.load() 的相关文章

随机推荐

  • 如何解决ajax和php中JSON数据的SyntaxError:JSON.parse:第1行第1列的意外字符

    如何解决这个错误 SyntaxError JSON parse unexpected character at line 1 column 1 of the JSON data 我正在向 ajax 和 php 发送一些数据 这是我的ajax
  • DrawerLayout 必须使用 MeasureSpec.EXACTLY 错误进行测量

    我正在尝试实现导航抽屉 但我不断收到此错误 我看到了类似的问题 但对我不起作用 我有以下布局activity main2 xml
  • TensorFlow“模块”对象没有属性“global_variables_initializer”

    我是张量流新手 我正在 iPython 笔记本上运行 Udacity 的深度学习作业 link https github com tensorflow tensorflow blob master tensorflow examples u
  • pandas加入DataFrame强制后缀?

    如何在合并或连接上强制使用后缀 我知道如果发生冲突 可以提供一个 但在我的情况下 我将 df1 与 df2 合并 这不会导致任何冲突 但然后在使用后缀的 df2 上再次合并 但我希望每次合并都有一个后缀 因为如果我按照你的想象进行不同的组合
  • Spark错误:parquet.column.values.dictionary.PlainValuesDictionary$PlainIntegerDictionary

    我在从配置单元表读取 Spark 数据帧时遇到问题 我将数据框存储为 dataframe coalesce n files write option mergeSchema true mode overwrite parquet table
  • 获取时、分、秒、毫秒、微秒的时间

    我有这个代码 SimpleDateFormat sDate new SimpleDateFormat yyyy MM dd HH mm ss 我知道这段代码返回时间中的小时 分钟 秒 我怎样才能得到毫秒和微秒 您不会有微秒 因为 Date
  • R 在 HPC MPIcluster 上运行 foreach dopar 循环

    我可以访问带有 MPI 分区的 HPC 集群 我的问题是 无论我尝试什么 我的代码 在我的 PC 上运行良好 都无法在 HPC 集群上运行 代码如下所示 图书馆 TM 图书馆 qdap 图书馆 雪 图书馆 doSNOW 库 foreach
  • 创建 24 位 WAV 文件需要做什么特别的事情吗?

    我可以成功创建 16 位 wav 文件 但创建 24 位文件时 我听到的只是白噪声 我正在设置 24 位有符号整数数据块 我是否必须在 wav 文件头的第 20 字节处设置一些特殊的音频格式 我目前使用的是格式1 Edit 1 The wB
  • 如何在 Swift 中在地图图钉周围添加圆圈?

    我一直在试图解决这个问题 但没有运气 我可以做什么 显示用户当前位置 在我想要的任何地方显示图钉 取决于纬度和经度 我不明白的是 如何围绕该位置创建地理围栏 func setupData 1 check if system can moni
  • Object.Create() 在幕后做什么?

    我正在深入研究 JavaScript 的原型继承 当使用 Object Create 创建对象时 有人可以展示幕后发生了什么吗 Object Create 是否依赖于幕后的 new 和构造函数 When Object create 用于创建
  • 为什么 C++ 隐式转换有效,但显式转换无效?

    以下代码在 C 11 中编译成功 include json hpp using json nlohmann json using namespace std int main json js asd string s1 js lt comp
  • 如何获取 firestore 文档中的字段?

    我正在开发一些与 Firestore 配合使用的云功能 我正在尝试获取特定文档的字段列表 例如 我有一个文档参考even data ref 但我不确定该文档是否包含我正在查看的字段 我想获取字段名称的列表 但我不知道该怎么做 我试图使用Ob
  • 使用目录树和过滤填充 TTreeView

    在 Lazarus 0 9 28 2 项目上我有一个TTreeView 与名字DirTree在我的表格上 frmConvert 但我想用所有目录树填充它 因为C 像这样 C 目录树 http i imagehost org 0185 cdi
  • 卷曲 IP 地址

    我需要发送一个带有用户 IP 地址而不是服务器 IP 地址的卷曲请求 我尝试了这个但没有运气 curl setopt ch CURLOPT INTERFACE ip 有任何想法吗 好吧 所以没有办法安全地欺骗curl请求的ip地址 但我发现
  • 2 的幂公式帮助

    我知道 Java 中的 2 i i i 1 1 可以让我找到一个数字是否是 2 的幂 但是有人可以解释为什么这样做吗 2 i i i 1 1 基本上 如果i是 2 的幂 它将有一个1在其位模式中 如果从中减去 1 则该值的所有低位1有点变成
  • LinkedIn 验证用户身份验证令牌服务器端

    经过一天的研究 我以以下问题结束 我正在使用 ember js 构建一个 Web 应用程序 目前我正在使用 linkedin javascript sdk 实现 LinkedIn 登录 我遇到的问题是 在收到用户信息 令牌 电子邮件 名字等
  • 为什么 SSLSocketFactory 缺少 setEnabledCipherSuites?

    SSLSocketFactory提供getDefaultCipherSuites 默认情况下在套接字上启用的密码 和getSupportedCipherSuites 如果需要 可以启用密码 然而 SSLSocketFactory不提供set
  • 迭代 MultiDict 中的键和所有值

    我有一本字典 params ImmutableMultiDict dataStore tardis symbol 1 symbol 2 我希望能够迭代字典并获取所有值及其键的列表 但是 当我尝试这样做时 它只获取第一个符号键值对并忽略另一个
  • 选择更改事件 - Html.DropDownListFor

    我有两个下拉列表 从第一个值中选择的值加载另一个值 当控制器中有辅助方法时 我该如何做到这一点 using Html BeginForm div table width 100 cellpadding 0 cellspacing 0 tr
  • 添加 BouncyCastle 提供程序会破坏 KeyStore.load()

    我使用以下命令生成了密钥库 keytool genkeypair keystore test ks storetype pkcs12 然后我运行以下测试 base64 代表我创建的密钥库 private static final Strin