Certificate 为什么我不能以某种方式将使用keytool生成的公钥证书导入Firefox?

Certificate 为什么我不能以某种方式将使用keytool生成的公钥证书导入Firefox?,certificate,x509,keytool,pki,Certificate,X509,Keytool,Pki,我正在尝试为CA2生成证书,以便: 有一个根CA叫做CA0。 有一种叫做CA1的中间CA。 还有另一种中间钙叫做CA2。 CA0签署CA1证书。 CA1签署CA2证书。 我使用keytool使用各种方法生成CA2 方法1:CA0签署CA1并写入文件;CA1签署CA2并写入文件;CA0从密钥库导出到文件 当我打开Firefox并进入Preferences>Advanced>View Certificates>Authority时,单击Import并逐个导入ca0.cer、ca1.cer和ca2.c

我正在尝试为CA2生成证书,以便:

有一个根CA叫做CA0。 有一种叫做CA1的中间CA。 还有另一种中间钙叫做CA2。 CA0签署CA1证书。 CA1签署CA2证书。 我使用keytool使用各种方法生成CA2

方法1:CA0签署CA1并写入文件;CA1签署CA2并写入文件;CA0从密钥库导出到文件 当我打开Firefox并进入Preferences>Advanced>View Certificates>Authority时,单击Import并逐个导入ca0.cer、ca1.cer和ca2.cer,它们可以很好地导入。然后,如果我选择CA2并单击查看>详细信息,我可以在证书层次结构窗格中看到完整的证书链。这一切都很好

方法2:CA0对CA1进行签名并将其导入密钥库;CA1签署CA2并将其导入密钥库;CA0、CA1和CA2从密钥库导出到文件 同样,我可以将ca0.cer、ca1.cer和ca2.cer导入Firefox中的权威

方法3:CA0对CA1进行签名并将其导入密钥库;CA1签名和CA2并导出到文件;CA0和CA1从密钥库导出到文件 这一次我可以将ca0.cer和ca1.cer导入Firefox的权威,但我不能导入ca2.cer。当我在“选择包含要导入的CA证书的文件”对话框中选择ca2.cer并单击“打开”时,什么也没有发生。对话框消失,证书不会出现在“权限”窗格中。

keytool-export仅将链中的第一个证书写入到-outfile,请参阅:

如果别名引用受信任的证书,则输出该证书。否则,别名是指具有关联证书链的密钥项。在这种情况下,将返回链中的第一个证书

而keytool-gencert将整个链写入-outfile。您可以看到,将PEM格式的-rfc输出添加到命令时:

-----BEGIN CERTIFICATE-----
MIICqDCCAmagAwIBAgIEHhRohzALBgcqhkjOOAQDBQAwDjEMMAoGA1UEAxMDQ0ExMB4XDTE2MDYw
...
hkjOOAQDBQADLwAwLAIUfkhluVSKCpemYFYfKf2KfT7UQaACFFA8SLiKbfOo6xh5e01S1YXJhM/P
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIICqDCCAmagAwIBAgIEZgEJrjALBgcqhkjOOAQDBQAwDjEMMAoGA1UEAxMDQ0EwMB4XDTE2MDYw
...
hkjOOAQDBQADLwAwLAIUd2DS+rPrJqlGwziqenDdVaYQWaoCFHleJS/5XfDk+GaEMSUw53gQ0vd7
-----END CERTIFICATE-----
因此,ca2.cer包含两个DER格式的证书CA1和ca2,只是简单地连接起来。Firefox无法处理这一点也不奇怪

我认为没有任何标准允许连接DER证书。PKCS7将是证书链的常用二进制格式。连接的PEM文件也很常见,但不是DER

文件中没有提到将链写入文件。事实上,它说X.509证书:

如果省略,该命令从标准输入中读取来自infle的请求,使用alias的私钥对其进行签名,如果省略,则将X.509证书输出到outfile中,并输出到标准输出

看一下,它将生成的证书写入文件和链-不包括根:

dumpCert(cert, out);
for (Certificate ca: keyStore.getCertificateChain(alias)) {
    if (ca instanceof X509Certificate) {
        X509Certificate xca = (X509Certificate)ca;
        if (!isSelfSigned(xca)) {
            dumpCert(xca, out);
        }
     }
}

根证书不包括在内,因为处理端将验证到根CA的信任锚点的链,这与SSL链验证的概念相同

问得好。顺便说一句,您为方法1粘贴了错误的命令,它们来自方法3,但与答案无关。@Omikron感谢您注意到错误。我已经用我想发布的实际步骤修复了方法1。你知道为什么ca2.cer只包含CA1和ca2吗?为什么它不含CA0?我该怎么做才能在keytool-gencert的输出中也包含CA0呢?
# Start afresh
rm -f foo.jks
rm -f *.cer

# Generate self-signed CA0 (root), CA1 (intermediate) and CA2 (another intermediate).
keytool -genkeypair -keystore foo.jks -storepass stpass -alias ca0 -keypass kpass0 -dname CN=CA0 -ext bc=ca:true
keytool -genkeypair -keystore foo.jks -storepass stpass -alias ca1 -keypass kpass1 -dname CN=CA1
keytool -genkeypair -keystore foo.jks -storepass stpass -alias ca2 -keypass kpass2 -dname CN=CA2

# CA0 signs CA1.
keytool -certreq -keystore foo.jks -storepass stpass -alias ca1 -keypass kpass1 |
keytool -gencert -keystore foo.jks -storepass stpass -alias ca0 -keypass kpass0 -ext bc=ca:true |
keytool -importcert -keystore foo.jks -storepass stpass -alias ca1 -keypass kpass1

# CA1 signs CA2.
keytool -certreq -keystore foo.jks -storepass stpass -alias ca2 -keypass kpass2 |
keytool -gencert -keystore foo.jks -storepass stpass -alias ca1 -keypass kpass1 -ext bc=ca:true -outfile ca2.cer

# Export CA0 and CA1
keytool -export -keystore foo.jks -storepass stpass -alias ca0 -file ca0.cer
keytool -export -keystore foo.jks -storepass stpass -alias ca1 -file ca1.cer
-----BEGIN CERTIFICATE-----
MIICqDCCAmagAwIBAgIEHhRohzALBgcqhkjOOAQDBQAwDjEMMAoGA1UEAxMDQ0ExMB4XDTE2MDYw
...
hkjOOAQDBQADLwAwLAIUfkhluVSKCpemYFYfKf2KfT7UQaACFFA8SLiKbfOo6xh5e01S1YXJhM/P
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIICqDCCAmagAwIBAgIEZgEJrjALBgcqhkjOOAQDBQAwDjEMMAoGA1UEAxMDQ0EwMB4XDTE2MDYw
...
hkjOOAQDBQADLwAwLAIUd2DS+rPrJqlGwziqenDdVaYQWaoCFHleJS/5XfDk+GaEMSUw53gQ0vd7
-----END CERTIFICATE-----
dumpCert(cert, out);
for (Certificate ca: keyStore.getCertificateChain(alias)) {
    if (ca instanceof X509Certificate) {
        X509Certificate xca = (X509Certificate)ca;
        if (!isSelfSigned(xca)) {
            dumpCert(xca, out);
        }
     }
}