来自 CA 的 PKCS12 Java 密钥库和 java 中的用户证书

发布于 2024-09-16 23:36:42 字数 1415 浏览 1 评论 0原文

我最近被任命负责用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

野生奥特曼 2024-09-23 23:36:42

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

您在第一次尝试中尝试做的是单独存储证书,这是行不通的。

您在第二次尝试中尝试做的事情(ks.setKeyEntry("SomeAlias", userCert.getPublicKey().getEncoded(), chain))是用公钥代替什么应该是私钥(请参见 KeyStore#setKeyEntry)。

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

关于 KeychainStore 的编辑

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

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

对此有一些注意事项:

  • 任何非空、非空密码都可以使用私钥(例如 "-".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 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.

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 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:

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

A couple of notes for this:

  • 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)
与他有关 2024-09-23 23:36:42

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文