PKCS12格式的Java密钥库:使用CA和用户证书在Java中建立密钥库

14

最近我被委任为在Java中模拟一个苹果产品(iPhone Configuration Utility)。我遇到了一些困难,其中之一是有关Exchange ActiveSync的部分。在那里,它允许您从Keychain中选择证书以用作EAS帐户的凭据。经过一些研究,我发现它实际上创建了一个PKCS12密钥库,插入了我选择的证书的私钥,并将其编码为XML。到目前为止还没有什么大问题。如果我使用Keychain Access创建.p12文件,则上传没有问题。但是,当我尝试将其转移到Java时,遇到了问题。

假设我将之前使用的其中一个证书导出为.cer文件(这是我们希望在环境中获得的内容)。现在将其上传到Java中,我会得到以下Certificate对象...

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"));

但是当我尝试使用另一个Excel文件时,它会发生问题。

ks.setCertificateEntry("SomeAlias", userCert);

我得到了异常...

java.security.KeyStoreException: TrustedCertEntry not supported

因此,我从证书转向密钥。但是,对于那些证书(我也获得了CA证书),我只能访问公钥,而不能访问私钥。如果我试图这样添加公钥...

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

我遇到了一个问题,在使用Java的Scanner类从控制台读取时,如果用户在输入时不按照要求的格式,会导致程序阻塞或出现异常。有没有一种方法可以让程序跳过错误的输入并继续读取后面的输入?

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

现在我在这里。有谁知道如何在Java中将.cer文件中的私钥导入到PKCS12密钥库中吗?我是否在正确的路上?

提前感谢!

2个回答

18
PKCS#12格式用于存储与证书链相关的私钥,两者都是必需的(尽管您可能不需要整个证书链)。虽然PKCS12密钥库类型很好地将此格式映射到Java KeyStore中,但出于这个原因,并非所有内容都受支持。
您在第一次尝试中要做的是仅存储证书,这是行不通的。而在第二次尝试中(ks.setKeyEntry("SomeAlias", userCert.getPublicKey().getEncoded(), chain)),您要做的是在应该是私钥的位置上提供公钥(请参见KeyStore#setKeyEntry)。 .cer 文件常常仅用于证书而非私钥(尽管扩展名最终只是一个指示)。如果您从导出您的.cer文件,则不会将私钥与其一起导出(这就是.p12 导出格式的用途)。
有关KeychainStore的编辑
如果您尝试进行此转换的原因最终是访问已在钥匙串中的私钥和证书,则可以直接从中加载它们。
KeyStore ks = KeyStore.getInstance("KeychainStore", "Apple");
ks.load(null, "-".toCharArray());

以下是一些注意事项:

  • 任何非空密码都可以用于使用私钥(例如 "-".toCharArray()),因为访问将由操作系统的安全服务提示(就像在其他应用程序中一样)。
  • 据我所知,仍存在一个错误,它仅允许访问一个私钥/证书对(即使密钥链中存在多个私钥/证书对)。

3

http://www.docjar.com/html/api/org/bouncycastle/jce/examples/PKCS12Example.java.html

这是如何将一个带有关联私钥的证书添加到PKCS12密钥库中。 当您使用客户端身份验证时,密钥库还需要包含私钥,在这种情况下,您使用KeyStore.getInstance("PKCS12")。

当您不使用客户端身份验证而仅使用服务器身份验证(并且私钥不会添加到密钥库中,因为它属于服务器)时,最好使用KeyStore.getInstance("JKS"),然后您可以将多个带有别名的证书添加到一个密钥库中。

据我所知,当您使用PKCS12时,只能添加1个带有私钥的证书(您必须添加整个证书链),以便用于该证书的私钥。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接