Getting this issue with spring boot properties:

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

Comment From: kumarvijay95

Earlier It was working fine with same configurations

Comment From: mhalbritter

Hello! How did you create the RSA key?

Comment From: kumarvijay95

Through Letsencrypt site. @mhalbritter

Comment From: mhalbritter

Could you generate a key pair for us with which we can reproduce the issue? I couldn't find that letsencrypt site you mentioned. Do you mean certbot?

Comment From: kumarvijay95

@mhalbritter Sorry.. yes It is certbot.

Comment From: kumarvijay95

@mhalbritter is this a bug in spring ??

Comment From: mhalbritter

I don't know. I didn't managed to get a RSA key generated by certbot yet. If you could provide us one, that would help greatly.

Comment From: mhalbritter

I just tried it with Java 17 and Spring Boot 3.0.6 / 3.1.0-RC2 / 3.1.0-SNAPSHOT and a certbot generated RSA key and can't reproduce it.

Comment From: kumarvijay95

@mhalbritter Let me check it again.. Could you pls check it with Java 11 and Spring Boot 2.7.7

Comment From: kumarvijay95

@mhalbritter could you please send me the properties because I am getting the same issue again.

Comment From: mhalbritter

It works with Java 11 and Spring Boot 2.7.7, too.

My properties don't help you, because something is wrong with your private key. Until you upload a sample with which we can reproduce the issue I fear that we can't help you here.

Comment From: kumarvijay95

@mhalbritter I have pasted the privkey.pem and fullchain.pem file as it was not allowing to upload .pem extension files.

Comment From: kumarvijay95

I created new server and created new keys... still getting same issue.. don't know why is it happening.

Comment From: mhalbritter

Thanks, I can now reproduce the issue. This key is not a RSA key, its a 256 bit elliptic curve key. That seems like a bug in boot.

Comment From: mhalbritter

keys.zip

This ZIP file contains a EC 256 bit key and the certificate for it. This leads to the stacktrace from the first comment. It looks like Boot tries to load it as a RSA key, which fails.

Looks like that Spring Boot 2.7.x is affected, too:

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

Comment From: mhalbritter

Problem is that in org.springframework.boot.web.server.PrivateKeyParser, this parser is used for parsing the key:

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

Which sets the algorithm to RSA. This is not correct in this case, it has to be "EC". Seems we need a more sophisticated logic to parse PKCS#8 keys which are not RSA keys.

Comment From: TomerBu

Facing the same issue: is there a workaround for the time being? some property we can set in application.properties? Export the key to another algorithm using openssh? Or a configuration bean to configure it correctly?

Comment From: kumarvijay95

@mhalbritter when will it be released ??

Comment From: wilkinsona

@kumarvijay95 you can find that information yourself by looking at the milestone to which the issue has been assigned (2.7.12 and 3.0.7 for the forward port) and their due dates (18 May).

Comment From: mhalbritter

Hey @TomerBu: RSA keys work fine, but I doubt you'll find a way to convert the EC key to RSA. Did you get the EC key through certbot, too? Maybe there's an option in certbot to force RSA keys?

You can also add the keys into a Java KeyStore, which you can then configure through the properties. That should work with EC keys, as the bug is in our own PEM parser. See this documentation for details.

Comment From: TomerBu

Hey @TomerBu: RSA keys work fine, but I doubt you'll find a way to convert the EC key to RSA. Did you get the EC key through certbot, too? Maybe there's an option in certbot to force RSA keys?

You can also add the keys into a Java KeyStore, which you can then configure through the properties. That should work with EC keys, as the bug is in our own PEM parser. See this documentation for details.

Yes. that's what I did and it works. for anyone with the same issue: certbot certonly --standalone --key-type rsa

we can also renew an existing certificate: certbot renew --key-type rsa --cert-name mydomain.com --force-renewal

Thank you!

Comment From: mhalbritter

Thanks for providing that workaround!