来自 CA 的 PKCS12 Java Keystore 和 Java 中的用户证书 [英] PKCS12 Java Keystore from CA and User certificate in java

查看:21
本文介绍了来自 CA 的 PKCS12 Java Keystore 和 Java 中的用户证书的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近负责用 Java 模拟 Apple 产品(iPhone 配置实用程序).我一直坚持的部分之一是关于 Exchange ActiveSync 的部分.在那里,它允许您从您的钥匙串中选择一个证书以用作您的 EAS 帐户的凭据.经过一番研究,我发现它实际上是在创建一个 PKCS12 密钥库,插入我选择的证书的私钥,并将其编码为 XML.到目前为止没什么大不了的.如果我使用 Keychain Access 创建一个 .p12 文件,它可以毫无问题地上传.但是当我尝试将其引入 Java 时遇到了问题.

I've recently been put in charge of mocking up an Apple product (iPhone Configuration Utility) in Java. One of the sections I've been a bit stuck on is a part about Exchange ActiveSync. In there, it allows you to select a certificate from your Keychain to use as credentials for your EAS account. After some research, I found that it's actually creating a PKCS12 keystore, inserting the private key of the certificate I selected, and encoding that into XML. So far not a big deal. If I create a .p12 file with Keychain Access it uploads without a problem. But I run into a problem when I try to bring that over to Java.

假设我将之前与 .p12 文件一起使用的那些证书之一导出为 .cer 文件(这是我们期望在环境中获得的).现在,当我将它上传到 Java 时,我会得到一个证书对象,如下所示...

Say I export one of those certs that I had used earlier with the .p12 file as a .cer file (this is what we are expecting to get in the environment). Now when I upload it into Java I get a Certificate object as follows...

KeyStore ks = java.security.KeyStore.getInstance("PKCS12");
ks.load(null, "somePassword".toCharArray());

CertificateFactory cf = CertificateFactory.getInstance("X.509", new BouncyCastleProvider());
java.security.cert.Certificate userCert  = cf.generateCertificate(new FileInputStream("/Users/me/Desktop/RecentlyExportedCert.cer"));

但是当我尝试...

ks.setCertificateEntry("SomeAlias", userCert);

我得到了例外...

java.security.KeyStoreException: TrustedCertEntry not supported

所以从证书我转向密钥.但是有了这些证书(我也获得了 CA 证书),我只能访问公钥,而不能访问私钥.如果我尝试像这样添加公钥......

So from certs I move onto keys. But with those Certificates (I got the CA Cert as well), I'm only able to access the public key, not the private. And if I attempt to add the public key like so...

java.security.cert.Certificate[] chain = {CACert};
ks.setKeyEntry("SomeAlias", userCert.getPublicKey().getEncoded(), chain);

我明白了……

java.security.KeyStoreException: Private key is not stored as PKCS#8 EncryptedPrivateKeyInfo: java.io.IOException: DerValue.getOctetString, not an Octet String: 3

所以现在我来了.有没有人知道如何将私钥从 .cer 文件获取到 Java 中的 PKCS12 密钥库?我是否走在正确的轨道上?

So now I'm here. Does anyone have any idea how to get a private key from a .cer file into a PKCS12 keystore in Java? Am I even on the right track?

提前致谢!

推荐答案

PKCS#12 格式用于存储与证书链关联的私钥,两者都是必需的(尽管您可能不需要整个链).尽管 PKCS12 密钥库类型在将此格式映射到 Java KeyStore 方面做得很好,但由于这个原因,并非所有东西都受支持.

The PKCS#12 format is intended for storing a private key associated with a certificate chain, and both are required (although you might not need the whole chain). Although the PKCS12 keystore type does a good job for mapping this format to a Java KeyStore, not everything is supported for this reason.

您第一次尝试做的是自行存储证书,但这是行不通的.

What you're trying to do in your first attempt is storing a certificate on its own, which won't work.

您在第二次尝试中尝试做的事情 (ks.setKeyEntry("SomeAlias", userCert.getPublicKey().getEncoded(), chain)) 是为了在应该是私钥的地方(参见 KeyStore#setKeyEntry).

What you're trying to do in your second attempt (ks.setKeyEntry("SomeAlias", userCert.getPublicKey().getEncoded(), chain)) is to for a public key in place of what should be a private key (see KeyStore#setKeyEntry).

.cer 文件往往只用于证书而不是私钥(当然,扩展名最终只是一个指示).如果你从 Keychain Access.app 导出你的 .cer 文件,你将不会得到私钥(这就是 .p12导出格式为).

.cer file tend to be just for certificates not private keys (although of course, the extension is ultimately just an indication). If you export your .cer file from Keychain Access.app, you won't get the private key with it (that's what the .p12 export format is for).

编辑关于 KeychainStore:

EDIT about KeychainStore:

如果您尝试进行此转换的原因最终是为了访问钥匙串中已有的私钥和证书,您可以直接从 KeychainStore 加载它们:

If the reason you're trying to do this conversion is ultimately to access private keys and certificates that are already in the keychain you could load them from the KeychainStore directly:

KeyStore ks = KeyStore.getInstance("KeychainStore", "Apple");
ks.load(null, "-".toCharArray());

一些注意事项:

  • 任何非空、非空密码都可以使用私钥(例如 "-".toCharArray()),因为操作系统的安全服务会提示访问(如将在其他应用程序中).
  • 据我所知,仍然存在一个错误和 它只允许访问一个私钥/证书对(即使钥匙串中存在多对私钥/证书对)
  • Any non-null, non-empty password will do to use the private key (e.g. "-".toCharArray()), as access will be prompted by the OS's security service (like it would in other applications).
  • As far as I'm aware, there is still a bug and it only allows access to one private key/certificate pair (even if a number of pairs of private key/certificate pairs are present in the keychain)

这篇关于来自 CA 的 PKCS12 Java Keystore 和 Java 中的用户证书的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆