导入SSL证书时出错:不是X.509证书

nik*_*kel 33 java security ssl x509certificate

我正在尝试按照这篇文章更新SSL证书 .

我是证书的菜鸟,所以我遵循了这个指南.但是,当我进入

keytool -keystore mycacerts -storepass changeit -importcert -file "C:\Users\Noks\Desktop\cacerts.pem" -v
Run Code Online (Sandbox Code Playgroud)

我收到错误:

keytool error: java.lang.Exception: Input not an X.509 certificate
java.lang.Exception: Input not an X.509 certificate
        at sun.security.tools.KeyTool.addTrustedCert(KeyTool.java:1913)
        at sun.security.tools.KeyTool.doCommands(KeyTool.java:818)
        at sun.security.tools.KeyTool.run(KeyTool.java:172)
        at sun.security.tools.KeyTool.main(KeyTool.java:166)
Run Code Online (Sandbox Code Playgroud)

我该如何解决?

Bru*_*der 34

您的cacerts.pem文件是否包含单个证书?因为它是一个PEM,看看它,它应该从一开始

-----BEGIN CERTIFICATE-----

结束

-----END CERTIFICATE-----

最后,要检查它是否已损坏,请抓住openssl并使用打印其详细信息

openssl x509 -in cacerts.pem -text

  • 问题也可能是`keytool`对空格和行结尾有点过分敏感.我试图导入_Let的Encrypt_证书,但由于这个原因它失败了,我用`openssl x509 -in broken.pem -out correct.pem`修复了证书格式,导入`correct.pem`没有问题. (8认同)
  • 线路应该已经在那了。如果不是,则您的证书可能是DER编码的(或无效的)。要进行转换,请执行“ openssl x509 -in mycert.der -inform DER -out myCert.pem -outform PEM”。要查看和验证它,请使用“ openssl -in myCert.pem -text”。该文件必须包含一个证书。 (2认同)
  • 小写x509很重要! (2认同)

sup*_*azy 31

许多CA将提供PKCS7格式的证书.

根据Oracle文档,keytool命令可以处理PKCS#7,但有时它会失败

keytool命令可以导入X.509 v1,v2和v3证书,以及由该类型证书组成的PKCS#7格式证书链.要导入的数据必须以二进制编码格式提供,或者以Internet RFC 1421标准定义的可打印编码格式(也称为Base64编码)提供.在后一种情况下,编码必须在开始时以一个以----- BEGIN开头的字符串为界,并在末尾以一个以----- END开头的字符串为界.

如果无法导入PKCS7文件,请尝试将其从PKCS7转换为X.509:

openssl pkcs7 -print_certs -in certificate.p7b -out certificate.cer
Run Code Online (Sandbox Code Playgroud)

  • 该文档没有明确说明的是,当您“-importcert”到现有私钥条目时,它需要一个“证书回复”,它可以是单个证书,也可以是包含使用“CertificateFactory.generateCertificates”的 PKCS7 的链(使用s 结尾),但是当您使用 `-importcert` 到一个新的 trustcert 条目时,它只需要一个证书,而不是使用 `generateCertificate` 的 PKCS7(无 s)。如果您想信任链中的多个证书(链接的目的是您不需要),则必须将它们单独导入到不同的别名。 (2认同)

小智 5

这似乎是一个老话题,但是我将在这里添加我的经验。我也尝试安装证书,并收到该错误。然后,我使用txt编辑器打开cer文件,并注意到每行末尾都有一个多余的空格(字符)。删除这些行使我可以导入证书。

希望这对其他人有价值。


Mik*_*kis 5

正如该问题的各种其他答案所示,此错误消息有许多不同的可能原因。它发生在你身上的原因可能与它发生在我身上的原因完全不同。不幸的是,错误消息完全没有指出问题的实际根源,因此对于故障排除完全没有帮助。事实上,这完全是一种误导。

因此,我不会向您提供导致此错误消息的无数可能原因,而是向您展示如何解决此问题,以便找出在您的特定情况下导致该问题的原因。

在工作中,我们通常使用以下两个命令来使某些软件能够与各种服务器通信,例如使 IntelliJ IDEA 能够与我们内部的 Maven 存储库通信:

[Elevated]keytool 
    -printcert -rfc -sslserver maven.services.{our-company}.com:443 > public.crt

[Elevated]keytool
    -import -storepass changeit -noprompt -trustcacerts -alias services.{our-company}.com 
    -keystore lib\security\cacerts -file public.crt
Run Code Online (Sandbox Code Playgroud)

现在,有时会发生该keytool -printcert命令无法完成其工作的情况,要么是由于配置错误,要么只是因为临时连接问题,例如防火墙阻止它、用户忘记启动其 VPN 等。这可能会发生,这是生活中的事实。这实际上不是问题。

问题是,当愚蠢的工具遇到这样的错误时,它不会将错误消息发送到标准错误设备,而是将其发送到标准输出设备!

所以这就是最终发生的事情:

  • 当您执行第一个命令时,您不会看到任何错误消息,因此您不知道它失败了。public.crt但是,该文件现在包含一条错误消息,而不是密钥keytool error: java.lang.Exception: No certificate from the SSL server
  • 当您执行第二个命令时,它会读取public.crt并找到错误消息的文本而不是其中的键,因此它失败,并显示keytool error: java.lang.Exception: Input not an X.509 certificate

底线是:在继续运行之前keytool -printcert ... > public.crt始终转储内容public.crt以确保它实际上是密钥而不是错误消息keytool -import ... -file public.crt