以编程方式将 PEM 证书导入 Java KeyStore

2024-05-10

我有一个由两个文件(.crt 和 .key)组成的客户端证书,我希望将其导入到 java KeyStore 中,然后在 SSLContext 中使用,以通过 Apache 的 HTTPClient 发送 HTTP 请求。但是,我似乎找不到一种以编程方式执行此操作的方法,我发现的大多数其他问题要么指向外部工具,要么不适合我的情况。

我的证书使用典型的“BEGIN CERTIFICATE”进行编码,后跟 Base64 编码字符串,密钥采用“BEGIN RSA PRIVATE KEY”,然后是另一个 Base64 编码字符串。

这是我到目前为止得到的:

private static SSLContext createSSLContext(File certFile, File keyFile) throws IOException {
    try {
        PEMParser pemParser = new PEMParser(new FileReader(keyFile));
        JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(new BouncyCastleProvider());
        Object object = pemParser.readObject();
        KeyPair kp = converter.getKeyPair((PEMKeyPair) object);
        PrivateKey privateKey = kp.getPrivate();

        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
        FileInputStream stream = new FileInputStream(certFile);
        X509Certificate cert = (X509Certificate) certFactory.generateCertificate(stream);

        KeyStore store = KeyStore.getInstance("JKS");
        store.load(null);
        store.setCertificateEntry("certificate", cert);
        store.setKeyEntry("private-key", privateKey, "changeit".toCharArray(), new Certificate[] { cert });

        SSLContext sslContext = SSLContexts.custom()
                .loadKeyMaterial(store, "changeit".toCharArray())
                .build();
        return sslContext;
    } catch (IOException | NoSuchAlgorithmException | CertificateException | KeyStoreException | KeyManagementException | UnrecoverableKeyException e) {
        throw new IOException(e);
    }
}

堆栈跟踪:

java.io.IOException:java.security.spec.InvalidKeySpecException:java.security.InvalidKeyException:无效的密钥格式 在 me.failedshack.ssltest.SSLTest.createSSLContext(SSLTest.java:80) 在 me.failedshack.ssltest.SSLTest.main(SSLTest.java:31)

引起原因:java.security.spec.InvalidKeySpecException:java.security.InvalidKeyException:无效的密钥格式 在 java.base/sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:216) 在 java.base/java.security.KeyFactory.generatePrivate(KeyFactory.java:390) 在 me.failedshack.ssltest.SSLTest.createSSLContext(SSLTest.java:62) ... 1 更多

引起原因:java.security.InvalidKeyException:密钥格式无效 在 java.base/sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:330) 在 java.base/sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:355) 在 java.base/sun.security.rsa.RSAPrivateCrtKeyImpl.(RSAPrivateCrtKeyImpl.java:91) 在 java.base/sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(RSAPrivateCrtKeyImpl.java:75) 在 java.base/sun.security.rsa.RSAKeyFactory.generatePrivate(RSAKeyFactory.java:315) 在 java.base/sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:212) ... 3 更多

遗憾的是,当我从文件生成私钥时,我不断收到 InvalidKeyException 异常。


类型的 PEM 文件RSA PRIVATE KEY是 base64 不是二进制,更重要的是采用 PKCS1 格式而不是 PKCS8,因此不能作为PKCS8EncodedKeySpec.

您的选择是:

  • 将 PKCS1 PEM 格式转换为 PKCS8(未加密)PEM 格式;读取该内容并删除标头和尾部行,将 Base64 解码为二进制并将其放入PKCS8EncodedKeySpec-- 但你说你不需要外部工具,而且将私钥 PLUS 证书(或链)转换为 PKCS12 (DER) 也同样容易alreadyJava 密钥库并避免该问题

  • 将 PKCS1 PEM 格式转换为 PKCS8(未加密)DER 格式,您可以将其作为二进制读取并放入PKCS8EncodedKeySpec——同上

  • 如果 PKCS1 PEM 未加密,请按照上述方式将其读取并解码为 PKCS1 DER,然后手动构建 PKCS8(未加密)编码,并使用该编码

  • 如果 PKCS1 PEM 已加密(您可以检测到它,因为除了 base64 之外,它的主体还包含两个 822 样式的标题行),您必须复制 OpenSSL 的“旧版”密钥文件解密,再加上构建 PKCS8(未加密)编码

  • 如果你可以专门使用 BouncyCastlebcpkix,可以直接读取解析allOpenSSL 用于私钥的 PEM 变体,包括解密加密的私钥;但是,如果您尚未使用它,则需要安装和/或部署一个额外的 jar

查看以下一个或多个骗局:
加载证书到KeyStore (JAVA) https://stackoverflow.com/questions/50514553/load-certificate-to-keystore-java(Q使用BouncyCastle构建PKCS8)
Java:将 DKIM 私钥从 RSA 转换为 JavaMail 的 DER https://stackoverflow.com/questions/23709898/java-convert-dkim-private-key-from-rsa-to-der-for-javamail(我的答案“手动”构造 PKCS8)
如何从文件加载 RSA 私钥 https://stackoverflow.com/questions/3243018/how-to-load-rsa-private-key-from-file(使用 BouncyCastle 阅读)
JAVA读取PKCS1格式的RSA私钥 https://stackoverflow.com/questions/41934846/read-rsa-private-key-of-format-pkcs1-in-java(使用 BouncyCastle 阅读)
从 RSA .pem 文件获取私钥 https://stackoverflow.com/questions/44681737/get-a-privatekey-from-a-rsa-pem-file(使用BC解密)
使用 Java 解密 OpenSSL PEM 编码的 RSA 私钥? https://stackoverflow.com/questions/35276820/decrypting-an-openssl-pem-encoded-rsa-private-key-with-java(手动解密)
maybe RSA 私钥的 PKCS#1 和 PKCS#8 格式 https://stackoverflow.com/questions/48958304/pkcs1-and-pkcs8-format-for-rsa-private-key(背景)
and “BEGIN RSA PRIVATE KEY”和“BEGIN PRIVATE KEY”之间的区别 https://stackoverflow.com/questions/20065304/differences-between-begin-rsa-private-key-and-begin-private-key(背景)

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

以编程方式将 PEM 证书导入 Java KeyStore 的相关文章

随机推荐

  • MVC3 中的 ModelState.IsValid 与 IValidatableObject

    所以根据Gu http weblogs asp net scottgu archive 2010 07 27 introducing asp net mvc 3 preview 1 aspx IValidatableObject Valid
  • 如何创建新的私人文本频道并向其中添加 2 个人?

    我正在创建一个不和谐的机器人 用户将向机器人发送消息并 机器人将创建一个新的私人文本通道 最好与机器人位于同一服务器上 机器人只会将消息传递用户和管理员添加到频道 我已经能够使用创建一个新频道这个问题 https stackoverflow
  • 日期减去 xslt 中的另一个日期

    希望有人能帮忙 我正在尝试比较 XML 文件中的 2 个日期并使用 XSLT 进行一些计算 例如 我有 2 个 XML 日期 2011 05 23 和 2011 04 29 我想在 XSLT 中进行计算 如下所示 2011 05 23 20
  • V8 如何管理它的堆?

    我知道V8的垃圾收集在工作时 会从GC的root开始追踪 这样无法到达的对象就会被标记然后被清除 我的问题是GC是如何遍历那些对象的 必须有一个数据结构来存储所有可达或不可达的对象 位图 链接表 顺便说一句 JVM 也做同样的事情吗 艾伦秀
  • 为什么单击拖动手柄不会夺走文本焦点?

    我有一个带有一些文本的 divhttp jsfiddle net MuCeD 2 http jsfiddle net MuCeD 2 如果我双击 div 中的 sample 一词 它就会突出显示 如果我然后单击页面上的其他任何位置 文本就会
  • Python 在 anaconda 中找不到 h2o 包

    当我尝试导入 h2o 时 我被告知该包不存在 当我尝试安装它时 它告诉我它已经存在 我尝试将其从计算机中删除并重新安装 但没有成功 此时我能想到的只是一些环境变量 C Users Lanier Anaconda2 C Users Lanie
  • JPanel透明背景和显示元素[重复]

    这个问题在这里已经有答案了 我插入一个背景图e 变成 aJPanel但一些界面元素消失了 以下 Java Swing 元素不会出现 标签标题 标签 usuario 标签 密码 按钮加速器 你能否使图像透明或元素不透明 setOpaque f
  • 修复 JSLint“意外的‘this’。”错误?

    我试图让以下代码成为符合 jslint 标准 http jslint com 但我陷入以下两个错误 本来应该看到一个声明 结果却看到了一个块 and 意想不到的 这个 我应该对我的代码进行哪些更改才能使 JSLint 满意 var pvAc
  • 修复了当 CSS 过滤器应用于 Microsoft Edge 中的同一元素时不起作用的位置

    我正在 Edge 20 10240 16384 0 上测试这个 我有一个位置固定的元素 并且应用了 CSS 过滤器 这在除 Microsoft Edge 之外的所有浏览器中都非常有效 其中元素的位置不保持固定 此问题与 CSS3 过滤器直接
  • 如何使用 wampserver 在本地系统上将 URL 从“localhost”更改为其他内容?

    在 Windows 计算机上 有一个系统在本地 wampserver 上运行 但当应用程序在 localhost 上运行时 URL 却另有说明 虽然我希望基于目录结构的 URL 是这样的 http localhost pro include
  • MAC 上的 QT/C++ - 未设置应用程序图标

    我正在努力解决的奇怪问题 在与我的 pro QT 项目文件相同的文件夹中 我有一个 Resources myIcon png 我试图将其设置为我构建的应用程序的图标 在 OSX 上运行 我阅读了文档 它建议在 pro 文件中添加 ICON
  • Java Swing:清除JList而不触发监听器

    我的情况如下 我有一个 JList 只要在列表中进行选择 它就会触发搜索 使用 ListSelectionListener 我正在尝试使用以下命令重置列表上的选择list clearSelection 这样做的问题是使用clearSelec
  • 如何处理 ReST 中的两个破折号

    我正在使用 Sphinx 来记录用 Python 编写的命令行实用程序 我希望能够记录命令行选项 例如 region像这样 region
  • D3.js分组条形图

    I am making a bar chart using D3 js like this source statcan gc ca http www statcan gc ca pub 12 593 x 2007001 figures f
  • 如何在 firebase 中监视子子添加事件

    有没有办法用 firebase 监视 grandchild added 事件 我已经使用node js javascript 库为child added 设置了一个观察者 但是当添加子项的子项时它不会触发 我正在设置会员状态信息 并想知道用
  • 超时 jQuery 效果

    我试图让一个元素淡入 然后在 5000 毫秒内再次淡出 我知道我可以做类似的事情 setTimeout function notice fadeOut 5000 但这只会控制淡出 我会在回调中添加上述内容吗 Update 从 jQuery
  • 目前最好的 Javascript 模板引擎是什么? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 遏制gem安装:捆绑安装失败,但正常gem安装有效[关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions solve
  • 如何使用修改后的索引来旋转 pandas 数据框?

    我有一个以下形式的时间序列数据框 rng pd date range 1 1 2013 periods 1000 freq 10min ts pd Series np random randn len rng index rng ts ts
  • 以编程方式将 PEM 证书导入 Java KeyStore

    我有一个由两个文件 crt 和 key 组成的客户端证书 我希望将其导入到 java KeyStore 中 然后在 SSLContext 中使用 以通过 Apache 的 HTTPClient 发送 HTTP 请求 但是 我似乎找不到一种以