[spring-projects/spring-boot]无法将 PEM 编码的 PKCS#8 EC 密钥与 server.ssl.certificate-private-key 一起使用

2024-06-26 418 views
8

使用 spring boot 属性遇到此问题:

server.ssl.certificate-private-key=/privkey.pem
server.ssl.certificate=/fullchain.pem
org.springframework.context.ApplicationContextException: Unable to start web server
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:164) ~[spring-boot-3.1.0-SNAPSHOT.jar!/:3.1.0-SNAPSHOT]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:578) ~[spring-context-6.0.8.jar!/:6.0.8]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.1.0-SNAPSHOT.jar!/:3.1.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:733) ~[spring-boot-3.1.0-SNAPSHOT.jar!/:3.1.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:435) ~[spring-boot-3.1.0-SNAPSHOT.jar!/:3.1.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:311) ~[spring-boot-3.1.0-SNAPSHOT.jar!/:3.1.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1305) ~[spring-boot-3.1.0-SNAPSHOT.jar!/:3.1.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1294) ~[spring-boot-3.1.0-SNAPSHOT.jar!/:3.1.0-SNAPSHOT]
        at com.smarthome.resourceserver.ResourceserverApplication.main(ResourceserverApplication.java:11) ~[classes!/:0.0.1-SNAPSHOT]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) ~[resourceserver-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:95) ~[resourceserver-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) ~[resourceserver-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) ~[resourceserver-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
Caused by: java.lang.IllegalStateException: Could not load store: Unable to create key store: Error loading private key file: Unexpected key format
        at org.springframework.boot.web.embedded.tomcat.SslConnectorCustomizer.configureSslStoreProvider(SslConnectorCustomizer.java:124) ~[spring-boot-3.1.0-SNAPSHOT.jar!/:3.1.0-SNAPSHOT]
        at org.springframework.boot.web.embedded.tomcat.SslConnectorCustomizer.configureSsl(SslConnectorCustomizer.java:93) ~[spring-boot-3.1.0-SNAPSHOT.jar!/:3.1.0-SNAPSHOT]
        at org.springframework.boot.web.embedded.tomcat.SslConnectorCustomizer.customize(SslConnectorCustomizer.java:59) ~[spring-boot-3.1.0-SNAPSHOT.jar!/:3.1.0-SNAPSHOT]
        at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.customizeSsl(TomcatServletWebServerFactory.java:367) ~[spring-boot-3.1.0-SNAPSHOT.jar!/:3.1.0-SNAPSHOT]
        at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.customizeConnector(TomcatServletWebServerFactory.java:344) ~[spring-boot-3.1.0-SNAPSHOT.jar!/:3.1.0-SNAPSHOT]
        at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:203) ~[spring-boot-3.1.0-SNAPSHOT.jar!/:3.1.0-SNAPSHOT]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:183) ~[spring-boot-3.1.0-SNAPSHOT.jar!/:3.1.0-SNAPSHOT]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:161) ~[spring-boot-3.1.0-SNAPSHOT.jar!/:3.1.0-SNAPSHOT]
        ... 16 common frames omitted
Caused by: java.lang.IllegalStateException: Unable to create key store: Error loading private key file: Unexpected key format
        at org.springframework.boot.ssl.pem.PemSslStoreBundle.createKeyStore(PemSslStoreBundle.java:99) ~[spring-boot-3.1.0-SNAPSHOT.jar!/:3.1.0-SNAPSHOT]
        at org.springframework.boot.ssl.pem.PemSslStoreBundle.getKeyStore(PemSslStoreBundle.java:69) ~[spring-boot-3.1.0-SNAPSHOT.jar!/:3.1.0-SNAPSHOT]
        at org.springframework.boot.web.embedded.tomcat.SslConnectorCustomizer.configureSslStoreProvider(SslConnectorCustomizer.java:116) ~[spring-boot-3.1.0-SNAPSHOT.jar!/:3.1.0-SNAPSHOT]
        ... 23 common frames omitted
Caused by: java.lang.IllegalStateException: Error loading private key file: Unexpected key format
        at org.springframework.boot.ssl.pem.PemPrivateKeyParser.parse(PemPrivateKeyParser.java:126) ~[spring-boot-3.1.0-SNAPSHOT.jar!/:3.1.0-SNAPSHOT]
        at org.springframework.boot.ssl.pem.PemSslStoreBundle.createKeyStore(PemSslStoreBundle.java:94) ~[spring-boot-3.1.0-SNAPSHOT.jar!/:3.1.0-SNAPSHOT]
        ... 25 common frames omitted
Caused by: java.lang.IllegalArgumentException: Unexpected key format
        at org.springframework.boot.ssl.pem.PemPrivateKeyParser$PemParser.parse(PemPrivateKeyParser.java:165) ~[spring-boot-3.1.0-SNAPSHOT.jar!/:3.1.0-SNAPSHOT]
        at org.springframework.boot.ssl.pem.PemPrivateKeyParser$PemParser.parse(PemPrivateKeyParser.java:150) ~[spring-boot-3.1.0-SNAPSHOT.jar!/:3.1.0-SNAPSHOT]
        at org.springframework.boot.ssl.pem.PemPrivateKeyParser.parse(PemPrivateKeyParser.java:118) ~[spring-boot-3.1.0-SNAPSHOT.jar!/:3.1.0-SNAPSHOT]
        ... 26 common frames omitted
Caused by: java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: Invalid RSA private key
        at java.base/sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:253) ~[na:na]
        at java.base/java.security.KeyFactory.generatePrivate(KeyFactory.java:389) ~[na:na]
        at org.springframework.boot.ssl.pem.PemPrivateKeyParser$PemParser.parse(PemPrivateKeyParser.java:162) ~[spring-boot-3.1.0-SNAPSHOT.jar!/:3.1.0-SNAPSHOT]
        ... 28 common frames omitted
Caused by: java.security.InvalidKeyException: Invalid RSA private key
        at java.base/sun.security.rsa.RSAPrivateCrtKeyImpl.parseKeyBits(RSAPrivateCrtKeyImpl.java:361) ~[na:na]
        at java.base/sun.security.rsa.RSAPrivateCrtKeyImpl.<init>(RSAPrivateCrtKeyImpl.java:161) ~[na:na]
        at java.base/sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(RSAPrivateCrtKeyImpl.java:90) ~[na:na]
        at java.base/sun.security.rsa.RSAKeyFactory.generatePrivate(RSAKeyFactory.java:352) ~[na:na]
        at java.base/sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:249) ~[na:na]
        ... 30 common frames omitted
Caused by: java.io.IOException: Version must be 0
        at java.base/sun.security.rsa.RSAPrivateCrtKeyImpl.parseASN1(RSAPrivateCrtKeyImpl.java:326) ~[na:na]
        at java.base/sun.security.rsa.RSAPrivateCrtKeyImpl.parseKeyBits(RSAPrivateCrtKeyImpl.java:351) ~[na:na]
        ... 34 common frames omitted

回答

3

之前使用相同配置时运行良好

0

您好!您是如何创建 RSA 密钥的?

0

通过 Letsencrypt 网站。@mhalbritter

0

您能为我们生成一个密钥对,以便我们重现该问题吗?我找不到您提到的 letsencrypt 网站。您指的是 certbot 吗?

7

@mhalbritter 抱歉.. 是的,这是 certbot。

1

@mhalbritter 这是 spring 中的一个 bug 吗??

4

我不知道。我还没有设法获得由 certbot 生成的 RSA 密钥。如果您能给我们提供一个,那将大有帮助。

6

我刚刚尝试使用 Java 17 和 Spring Boot 3.0.6 / 3.1.0-RC2 / 3.1.0-SNAPSHOT 以及 certbot 生成的 RSA 密钥,但无法重现它。

8

@mhalbritter 让我再检查一下.. 您能用 Java 11 和 Spring Boot 2.7.7 检查一下吗

8

@mhalbritter 您能否将属性发送给我,因为我又遇到了同样的问题。

2

它也适用于 Java 11 和 Spring Boot 2.7.7。

我的属性无法帮助您,因为您的私钥有问题。除非您上传我们可以重现该问题的示例,否则我们恐怕无法为您提供帮助。

2

@mhalbritter 我粘贴了 privkey.pem 和 fullchain.pem 文件,因为它不允许上传 .pem 扩展文件。

1

我创建了新的服务器并创建了新的密钥......仍然遇到同样的问题......不知道为什么会发生这种情况。

9

谢谢,我现在可以重现这个问题了。这个密钥不是 RSA 密钥,而是 256 位椭圆曲线密钥。这似乎是启动时的一个错误。

8

钥匙.zip

此 ZIP 文件包含 EC 256 位密钥及其证书。这导致出现第一条注释中的堆栈跟踪。看起来 Boot 尝试将其加载为 RSA 密钥,但失败了。

看起来 Spring Boot 2.7.x 也受到了影响:

org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerException: Could not load store: Error loading private key file /home/moe/Desktop/key.pem
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:165) ~[spring-boot-2.7.11.jar:2.7.11]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:577) ~[spring-context-5.3.27.jar:5.3.27]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.11.jar:2.7.11]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:731) ~[spring-boot-2.7.11.jar:2.7.11]
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) ~[spring-boot-2.7.11.jar:2.7.11]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) ~[spring-boot-2.7.11.jar:2.7.11]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303) ~[spring-boot-2.7.11.jar:2.7.11]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292) ~[spring-boot-2.7.11.jar:2.7.11]
        at com.example.sb35322.Sb35322Application.main(Sb35322Application.java:10) ~[main/:na]
Caused by: org.springframework.boot.web.server.WebServerException: Could not load store: Error loading private key file /home/moe/Desktop/key.pem
        at org.springframework.boot.web.embedded.tomcat.SslConnectorCustomizer.configureSslStoreProvider(SslConnectorCustomizer.java:138) ~[spring-boot-2.7.11.jar:2.7.11]
        at org.springframework.boot.web.embedded.tomcat.SslConnectorCustomizer.configureSsl(SslConnectorCustomizer.java:96) ~[spring-boot-2.7.11.jar:2.7.11]
        at org.springframework.boot.web.embedded.tomcat.SslConnectorCustomizer.customize(SslConnectorCustomizer.java:61) ~[spring-boot-2.7.11.jar:2.7.11]
        at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.customizeSsl(TomcatServletWebServerFactory.java:366) ~[spring-boot-2.7.11.jar:2.7.11]
        at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.customizeConnector(TomcatServletWebServerFactory.java:343) ~[spring-boot-2.7.11.jar:2.7.11]
        at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:203) ~[spring-boot-2.7.11.jar:2.7.11]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:184) ~[spring-boot-2.7.11.jar:2.7.11]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:162) ~[spring-boot-2.7.11.jar:2.7.11]
        ... 8 common frames omitted
Caused by: java.lang.IllegalStateException: Error loading private key file /home/moe/Desktop/key.pem
        at org.springframework.boot.web.server.PrivateKeyParser.parse(PrivateKeyParser.java:130) ~[spring-boot-2.7.11.jar:2.7.11]
        at org.springframework.boot.web.server.CertificateFileSslStoreProvider.createKeyStore(CertificateFileSslStoreProvider.java:83) ~[spring-boot-2.7.11.jar:2.7.11]
        at org.springframework.boot.web.server.CertificateFileSslStoreProvider.getKeyStore(CertificateFileSslStoreProvider.java:51) ~[spring-boot-2.7.11.jar:2.7.11]
        at org.springframework.boot.web.embedded.tomcat.SslConnectorCustomizer.configureSslStoreProvider(SslConnectorCustomizer.java:130) ~[spring-boot-2.7.11.jar:2.7.11]
        ... 15 common frames omitted
Caused by: java.lang.IllegalArgumentException: Unexpected key format
        at org.springframework.boot.web.server.PrivateKeyParser$PemParser.parse(PrivateKeyParser.java:176) ~[spring-boot-2.7.11.jar:2.7.11]
        at org.springframework.boot.web.server.PrivateKeyParser$PemParser.parse(PrivateKeyParser.java:161) ~[spring-boot-2.7.11.jar:2.7.11]
        at org.springframework.boot.web.server.PrivateKeyParser.parse(PrivateKeyParser.java:122) ~[spring-boot-2.7.11.jar:2.7.11]
        ... 18 common frames omitted
Caused by: java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: Invalid RSA private key
        at java.base/sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:253) ~[na:na]
        at java.base/java.security.KeyFactory.generatePrivate(KeyFactory.java:389) ~[na:na]
        at org.springframework.boot.web.server.PrivateKeyParser$PemParser.parse(PrivateKeyParser.java:173) ~[spring-boot-2.7.11.jar:2.7.11]
        ... 20 common frames omitted
Caused by: java.security.InvalidKeyException: Invalid RSA private key
        at java.base/sun.security.rsa.RSAPrivateCrtKeyImpl.parseKeyBits(RSAPrivateCrtKeyImpl.java:361) ~[na:na]
        at java.base/sun.security.rsa.RSAPrivateCrtKeyImpl.<init>(RSAPrivateCrtKeyImpl.java:161) ~[na:na]
        at java.base/sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(RSAPrivateCrtKeyImpl.java:90) ~[na:na]
        at java.base/sun.security.rsa.RSAKeyFactory.generatePrivate(RSAKeyFactory.java:352) ~[na:na]
        at java.base/sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:249) ~[na:na]
        ... 22 common frames omitted
Caused by: java.io.IOException: Version must be 0
        at java.base/sun.security.rsa.RSAPrivateCrtKeyImpl.parseASN1(RSAPrivateCrtKeyImpl.java:326) ~[na:na]
        at java.base/sun.security.rsa.RSAPrivateCrtKeyImpl.parseKeyBits(RSAPrivateCrtKeyImpl.java:351) ~[na:na]
        ... 26 common frames omitted
9

问题在于,在中org.springframework.boot.web.server.PrivateKeyParser,这个解析器用于解析密钥:

parsers.add(new PemParser(PKCS8_HEADER, PKCS8_FOOTER, "RSA", PKCS8EncodedKeySpec::new));

将算法设置为 RSA。在这种情况下,这是不正确的,它必须是“EC”。看来我们需要更复杂的逻辑来解析不是 RSA 密钥的 PKCS#8 密钥。

0

面临同样的问题:暂时有解决方法吗?我们可以在 application.properties 中设置一些属性吗?使用 openssh 将密钥导出到另一种算法?或者配置 bean 以正确配置它?

2

@mhalbritter 什么时候发布??

9

嘿@TomerBu:RSA 密钥工作正常,但我怀疑您是否能找到将 EC 密钥转换为 RSA 的方法。您也是通过 certbot 获取 EC 密钥的吗?也许 certbot 中有一个强制使用 RSA 密钥的选项?

您还可以将密钥添加到 Java KeyStore 中,然后可以通过属性进行配置。这应该适用于 EC 密钥,因为错误出在我们自己的 PEM 解析器中。有关详细信息,请参阅此文档

3

是的。这就是我所做的,并且有效。对于遇到同样问题的人: certbot certonly --standalone --key-type rsa

我们还可以更新现有的证书: certbot renew --key-type rsa --cert-name mydomain.com --force-renewal

谢谢你!

9

感谢您提供解决方法!