我有一个名为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)?
答案 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
行应该是单独的行,而不是像你拥有的那样一起运行。