来自 CA 的 PKCS12 Java 密钥库和 java 中的用户证书
我最近被任命负责用 Java 模拟 Apple 产品(iPhone 配置实用程序)。我一直有点困惑的部分之一是有关 Exchange ActiveSync 的部分。在那里,您可以从钥匙串中选择一个证书作为您的 EAS 帐户的凭据。经过一番研究,我发现它实际上是创建一个 PKCS12 密钥库,插入我选择的证书的私钥,并将其编码为 XML。到目前为止没什么大不了的。如果我使用钥匙串访问创建 .p12 文件,它可以毫无问题地上传。但当我尝试将其移植到 Java 时遇到了问题。
假设我将之前与 .p12 文件一起使用的那些证书之一导出为 .cer 文件(这是我们期望在环境中获得的内容)。现在,当我将其上传到 Java 中时,我得到一个证书对象,如下所示...
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 证书),我只能访问公钥,而不能访问私钥。如果我尝试像这样添加公钥...
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 密钥库中?我是否走在正确的轨道上?
提前致谢!
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.
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"));
But when I try...
ks.setCertificateEntry("SomeAlias", userCert);
I get the exception...
java.security.KeyStoreException: TrustedCertEntry not supported
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);
I get...
java.security.KeyStoreException: Private key is not stored as PKCS#8 EncryptedPrivateKeyInfo: java.io.IOException: DerValue.getOctetString, not an Octet String: 3
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?
Thanks in advance!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
PKCS#12 格式用于存储与证书链关联的私钥,两者都是必需的(尽管您可能不需要整个链)。
尽管
PKCS12
密钥库类型可以很好地将此格式映射到 JavaKeyStore
,但由于这个原因,并非所有内容都受支持。您在第一次尝试中尝试做的是单独存储证书,这是行不通的。
您在第二次尝试中尝试做的事情(
ks.setKeyEntry("SomeAlias", userCert.getPublicKey().getEncoded(), chain)
)是用公钥代替什么应该是私钥(请参见KeyStore#setKeyEntry
)。.cer
文件往往仅用于证书而不是私钥(当然,扩展名最终只是一个指示)。如果您从 Keychain Access.app 导出.cer
文件,您将不会获得私钥(这就是.p12
导出格式为)。关于 KeychainStore 的编辑:
如果您尝试进行此转换的原因最终是为了访问钥匙串中已有的私钥和证书,您可以从
KeychainStore
加载它们直接:对此有一些注意事项:
"-".toCharArray()
),因为访问将由操作系统的安全服务(就像在其他应用程序中一样)。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 JavaKeyStore
, 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.
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 (seeKeyStore#setKeyEntry
)..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).EDIT about 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:A couple of notes for this:
"-".toCharArray()
), as access will be prompted by the OS's security service (like it would in other applications).http://www.docjar.com/html /api/org/bouncycastle/jce/examples/PKCS12Example.java.html
这是将具有关联私钥的证书添加到 PKCS12 密钥库的方法。
当您使用客户端身份验证时,密钥库还需要包含私钥,在这种情况下您使用 KeyStore.getInstance("PKCS12")。
当您不使用客户端身份验证而仅使用服务器身份验证(并且私钥不会添加到密钥库,因为它属于服务器)时,最好使用
KeyStore.getInstance("JKS"),您可以将多个带有别名的证书添加到该一个密钥库。
当您使用 PKCS12 时,据我所知,您只能添加 1 个与您想要用于该证书的私钥关联的证书(您必须添加整个证书链)。
http://www.docjar.com/html/api/org/bouncycastle/jce/examples/PKCS12Example.java.html
This is how to add a certificate with a associating private key to a PKCS12 keystore.
When you are using client authentication, the keystore needs to contain also the private key, in that case you use KeyStore.getInstance("PKCS12").
When youre not using client authentication but only server authentication(and private key will not be added to keystore, since it belongs to the server), its better to use
KeyStore.getInstance("JKS"), than you can add multiple certificates with an alias to that one keystore.
When you are using PKCS12, as far as I know, you can only add 1 certificate(you have to add the whole certificate chain) associated with the private key, you want to use for that certificate.