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



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

  1. 有一个名为CA0的根CA
  2. 有一种叫做CA1的中间CA
  3. 还有一种叫做CA2的中间CA
  4. CA0签署CA1证书
  5. CA1签署CA2的证书

我使用keytool使用各种方法生成CA2。

方法1:CA0对CA1进行签名并写入文件;CA1对CA2进行签名并写入文件;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 -outfile ca1.cer
# 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
keytool -export -keystore foo.jks -storepass stpass -alias ca0 -file ca0.cer

当我打开Firefox,进入"首选项">"高级">"查看证书">"权威机构",单击"导入"并逐一导入ca0.cer、ca1.cer和ca2.cer时,它们会被导入。然后,如果我选择CA2并单击查看>详细信息,我可以在证书层次结构窗格中看到完整的证书链。这一切都很好。

方法2:CA0对CA1进行签名并将其导入密钥库;CA1签署CA2并将其导入密钥库;CA0、CA1和CA2从密钥库导出到文件

# 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 |
keytool -importcert -keystore foo.jks -storepass stpass -alias ca2 -keypass kpass2
# Export CA0, CA1 and CA2
keytool -export -keystore foo.jks -storepass stpass -alias ca0 -file ca0.cer
keytool -export -keystore foo.jks -storepass stpass -alias ca1 -file ca1.cer
keytool -export -keystore foo.jks -storepass stpass -alias ca1 -file ca2.cer

同样,我可以在Firefox中将ca0.cer、ca1.cer和ca2.cer导入Authority。

方法3:CA0签署CA1并将其导入密钥库;CA1签署和CA2并导出到文件;CA0和CA1从密钥库导出到文件

# 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

这一次,我可以将ca0.cer和ca1.cer导入到Firefox的Authorities中,但我无法导入ca2.cer。当我在"选择要导入的包含CA证书的文件"对话框中选择ca2.cer并单击"打开"时,什么都不会发生。对话框将消失,证书不会显示在"权限"窗格中。

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

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

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

-----BEGIN CERTIFICATE-----
MIICqDCCAmagAwIBAgIEHhRohzALBgcqhkjOOAQDBQAwDjEMMAoGA1UEAxMDQ0ExMB4XDTE2MDYw
...
hkjOOAQDBQADLwAwLAIUfkhluVSKCpemYFYfKf2KfT7UQaACFFA8SLiKbfOo6xh5e01S1YXJhM/P
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIICqDCCAmagAwIBAgIEZgEJrjALBgcqhkjOOAQDBQAwDjEMMAoGA1UEAxMDQ0EwMB4XDTE2MDYw
...
hkjOOAQDBQADLwAwLAIUd2DS+rPrJqlGwziqenDdVaYQWaoCFHleJS/5XfDk+GaEMSUw53gQ0vd7
-----END CERTIFICATE-----

因此,ca2.cer包含两个DER格式的证书(CA1和ca2),只是连接在一起。Firefox无法处理这一点也就不足为奇了。

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

keytool文档中没有任何关于将链写入文件的内容。事实上,上面写着"X.509证书":

该命令从infile读取请求(如果省略,则从标准输入),使用别名的私钥对其进行签名,并将X.509证书输出到outfile(如果忽略,则输出到标准输出)。

查看keytool的来源,它将生成的证书写入文件和链-不包括根:

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链验证的概念相同)。

最新更新