【问题标题】:How to export public key from pkcs12 file programmatically如何以编程方式从 pkcs12 文件中导出公钥
【发布时间】:2015-04-21 06:35:13
【问题描述】:

我在尝试导出 pkcs12 文件中包含的公钥时遇到问题。我想要达到的结果与使用此命令的结果相同(但以编程方式):

keytool -export -alias mycertalias -keystore mykeystore.jks -rfc -file mypublickey.pem 

我获得了公钥并使用 BouncyCastle 生成了一个字符串,但是获得的结果与我使用上面的命令获得的结果不匹配。这是我的代码:

KeyStore keyStore = KeyStore.getInstance("pkcs12");
keyStore.load(new FileInputStream(certPath),certPassword.toCharArray());
String alias = "mycertalias";
Certificate cert = keyStore.getCertificate(alias);

PublicKey publicKey = cert.getPublicKey();   
StringWriter writer = new StringWriter();
PemWriter pemWriter = new PemWriter(writer);
pemWriter.writeObject(new PemObject("CERTIFICATE", publicKey.getEncoded()));
pemWriter.flush();
pemWriter.close();

System.out.println(writer.toString());

我尝试过不使用 BouncyCastle 并直接对字符串进行编码,但我得到的结果与以前相同(因此它与使用 keytool 命令获得的结果也不匹配):

Certificate cert = keyStore.getCertificate(alias);
BASE64Encoder encoder = new BASE64Encoder();
PublicKey publicKey = cert.getPublicKey();
System.out.println(new String(encoder.encode(publicKey.getEncoded())));

知道我做错了什么吗?提前感谢您的帮助。

更新:

正如@dave_thompson_085 所建议的那样,我真正想要的是以 PEM 格式导出整个证书,所以有效代码是这样的:

//...
Certificate cert = keyStore.getCertificate(alias);
StringWriter writer = new StringWriter();
PemWriter pemWriter = new PemWriter(writer);
pemWriter.writeObject(new PemObject("CERTIFICATE", cert.getEncoded()));
//...

谢谢!

【问题讨论】:

  • pemWriter.writeObject(new PemObject("CERTIFICATE", publicKey.getEncoded())); 这行对我来说似乎有问题,你应该将 PublicKey 转换为 Bouncycastle 格式:SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(publicKey.getEncoded()); 虽然我认为即使这一步是不必要的,只需写 pemWriter.writeObject(publicKey.getEncoded());
  • BC 的 PemWriter 的当前版本只接受 PemObjectGenerator 作为参数,它不再接受字节数组:public void writeObject(PemObjectGenerator objGen)
  • 哦。很高兴知道,谢谢。我想我正在查看一个较旧的来源。

标签: java bouncycastle public-key


【解决方案1】:

您的 keytool 示例执行 JKS 而不是 P12,但添加 -storetype pkcs12 会执行 P12,所以我假设这就是您的意思。更重要的是,keytool -exportcert(在大约 1.5 版本中正式取代了 -export)导出整个证书,而不仅仅是公钥。指定 -rfc 以 PEM 格式执行,并省略 -rfc以 DER 格式进行,但无论哪种方式,它都是整个证书。

您的第二个代码也不应该产生相同的结果;它应该产生,也许是模换行符,与 PEM 格式的 body 相同,但没有虚线 BEGIN 和 END 行。 BEGIN 和 END 行是 PEM 格式的一部分,没有它们就不是 PEM。如果没有说明 正确 类型的内容,你没有说明,它不是正确的 PEM。

如果您真的只想要公钥,您可以这样做,但不要期望它与证书相同,因为公钥不是证书。请注意,很少有应用程序可以在没有证书中其他数据的情况下单独使用公钥;唯一想到的是 SSH(据说可以手动确认身份和有效性),OpenSSH 不使用 Java JCE 支持的基于 ASN1 的“X509”(实际上是 SPKI)编码,而是使用它自己的基于 base64-MPI 的编码编码。

【讨论】:

  • 是的,很抱歉,我的用例有点复杂,所以为了简单起见,我混合了 keytool 命令,但正如你所说。你说的很对......事实上我正在寻找的只是这个:...... Certificate cert = keyStore.getCertificate(alias); StringWriter writer = new StringWriter(); PemWriter pemWriter = new PemWriter(writer); pemWriter.writeObject(new PemObject("CERTIFICATE", cert.getEncoded()));恐怕我误解了 .pem 文件的内容!非常感谢您的帮助
猜你喜欢
  • 2021-05-29
  • 2011-09-23
  • 2010-11-03
  • 2011-08-11
  • 1970-01-01
  • 1970-01-01
  • 2011-06-27
  • 2012-03-18
  • 2014-07-09
相关资源
最近更新 更多