如何将证书链添加到JKS

时间:2015-08-04 21:57:33

标签: ssl certificate keystore chain jks

我有一个名为cert.cer的证书链,其内容为:

subject= ... OU=MyCA
issuer= ... OU=MyCA
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----

subject= ... OU=Client
issuer= .. OU=MyCA
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----

我尝试通过调用:

将此链添加到JKS

keytool -import -trustcacerts -file cert.cer -keystore sample.keystore -storepass 123456 -alias chain

,仅添加OU = MyCA的顶级证书。

如何正确地将此链添加到JavaKeyStore(JKS)?

2 个答案:

答案 0 :(得分:7)

好的,我运行了命令,将证书合并为PKCS7格式:

openssl > crl2pkcs7 -nocrl -certfile a.crt -certfile b.crt -out outfile.p7b

工作了。     
然后我尝试使用以下命令将PKCS#7文件导入JKS文件:

keytool -import -trustcacerts -file outfile.p7b -keystore keystore1.jks -storepass 123456 -alias chain

它不起作用。
然后我研究了一下,发现我需要以Base64格式或Der格式的文件中的证书链。 我有Base64格式文件。所以,我尝试使用以下windows命令连接文件:

copy /b a.crt+b.crt c.crt

linux命令是:

cat a.crt b.crt > c.crt

因此输出文件如下所示:

-----BEGIN CERTIFICATE-----
..............................
..............................
-----END CERTIFICATE----------BEGIN CERTIFICATE-----
...............................
...............................
-----END CERTIFICATE-----

然后,尝试使用上述命令在JKS中导入证书链。有效。然后,我尝试从密钥库中查看证书列表。为此我运行了以下命令:

keytool -list -v -keystore keystore1.jks

但它说,只有" 1条目被发现"并显示了一个证书。由于密钥库未加载完整的证书链,实验失败。
因此,我尝试使用以下openssl命令转换证书链中的PKCS#7文件:

pkcs7 -print_certs -in outfile.p7b -out certificates.cer

输出文件看起来与您的完全一样,从主题dn和发行者dn开始,然后是页眉和页脚。然后我尝试将证书存储在' certificates.cer'到jks文件' keystore1.jks'。但是,再次,在导入之后,它表明,密钥库只有一个证书。因此,发行人dn和主题dn不是问题。
然后我尝试将Base64文件转换为Der文件,然后尝试连接数据:

openssl x509 -in a.crt -outform DER -out aa.crt
openssl x509 -in b.crt -outform DER -out bb.crt
copy /b aa.crt+bb.crt cc.crt

然后,我尝试将der concated文件导入JKS。但同样只导入了一个证书。

我真的想过我在做什么可能真的错了。因此,我查找了KeyTool的源代码,并找到了导入证书或证书链的方法。

Imports a JDK 1.1-style identity database. We can only store one certificate per identity, because we use the identity's name as the alias (which references a keystore entry), and aliases must be unique.

我很惊讶,他们的代码将输入流转换为证书列表,但它们仅使用证书的一个证书(第一个)。

if (certs!=null && certs.length>0) {
      // we can only store one user cert per identity.
      // convert old-style to new-style cert via the encoding
         DerOutputStream dos = new DerOutputStream()
         certs[0].encode(dos);
         .............................

因此,我们无法做到一次添加多个证书。策略是一个条目的一个证书。因此,如果您要输入多个证书,则必须单独输入。或者,编写一些java代码以使我们的工作变得简单(我总是这样做)。
很抱歉让这么久。但希望这可以清除你大部分的困惑。

答案 1 :(得分:7)

two kinds of entries in a JKS-type KeyStore

  • PrivateKey条目包含私钥以及该私钥的证书或证书链

  • TrustedCert条目包含一个证书而没有私钥

通用KeyStore接口允许第三种类型的条目用于SecretKey,但JKS不支持它,只有使用少得多的JCEKS,我相信BouncyCastle格式。

我找到了您的另一个问题https://security.stackexchange.com/questions/95945/how-to-add-a-certificate-chain-to-a-jks,这解释了为什么正确地不想要私钥输入。但是,您将为keytool等找到的大部分说明都是关于附加的一个链(通常从CA返回)到一个私钥,并掩盖一个事实,即你不能将一串证书存储为一个条目而不用一个私钥。

所以是的,必须单独输入每个证书。但是,不一定意味着您必须单独获取每个证书。 CertPathBuilder正好存在于从信任库中提取,例如(但不仅仅是)JKS 所有形成有效链的证书。不幸的是,使CertPathBuilder(特别是“PKIX”)适用于SSL / TLS所需的花哨功能使得使用更简单的应用程序变得非常笨拙,因此您可能更愿意只获取证书。

PS-concatenated PEM证书可以在允许链的情况下工作(仅使用私钥),但您显示的示例无效。 thread.isAlive() -----BEGIN行应该是单独的行,而不是像你拥有的那样一起运行。