如何以编程方式从 pkcs12 文件导出 public 密钥

How to export public key from pkcs12 file programmatically

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

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

我获取了public键并用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()));
//...

谢谢!

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

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

如果您真的只想要 public 密钥,您可以这样做,但不要指望它与证书相同,因为 public 密钥不是证书。请注意,很少有应用程序可以单独使用 public 密钥而无需证书中的其他数据;唯一想到的是 SSH(它应该手动确认身份和有效性),OpenSSH 不使用 Java JCE 支持的基于 ASN1 的 "X509"(真正的 SPKI)编码,而是使用它的自己的基于 base64-MPI 的编码。