Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't use PEM encoded PKCS#8 EC keys with server.ssl.certificate-private-key #35322

Closed
kumarvijay95 opened this issue May 5, 2023 · 22 comments
Closed
Assignees
Labels
theme: ssl Issues related to ssl support type: bug A general bug
Milestone

Comments

@kumarvijay95
Copy link

kumarvijay95 commented May 5, 2023

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
@kumarvijay95
Copy link
Author

Earlier It was working fine with same configurations

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label May 5, 2023
@mhalbritter
Copy link
Contributor

mhalbritter commented May 5, 2023

Hello! How did you create the RSA key?

@mhalbritter mhalbritter added the status: waiting-for-feedback We need additional information before we can continue label May 5, 2023
@kumarvijay95
Copy link
Author

Through Letsencrypt site. @mhalbritter

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels May 5, 2023
@mhalbritter
Copy link
Contributor

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?

@mhalbritter mhalbritter added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels May 8, 2023
@kumarvijay95
Copy link
Author

@mhalbritter Sorry.. yes It is certbot.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels May 8, 2023
@mhalbritter mhalbritter changed the title Invalid RSA Key while applying SSL with pem files Invalid RSA Key when using CertBot generated PEM file May 8, 2023
@mhalbritter mhalbritter changed the title Invalid RSA Key when using CertBot generated PEM file Invalid RSA private key when using CertBot generated PEM file May 8, 2023
@kumarvijay95
Copy link
Author

@mhalbritter is this a bug in spring ??

@mhalbritter
Copy link
Contributor

mhalbritter commented May 8, 2023

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.

@mhalbritter
Copy link
Contributor

mhalbritter commented May 8, 2023

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.

@mhalbritter mhalbritter added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels May 8, 2023
@kumarvijay95
Copy link
Author

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

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels May 9, 2023
@kumarvijay95
Copy link
Author

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

@mhalbritter
Copy link
Contributor

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.

@mhalbritter mhalbritter closed this as not planned Won't fix, can't repro, duplicate, stale May 9, 2023
@mhalbritter mhalbritter added status: invalid An issue that we don't feel is valid and removed status: waiting-for-triage An issue we've not yet triaged status: feedback-provided Feedback has been provided labels May 9, 2023
@kumarvijay95
Copy link
Author

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

@mhalbritter mhalbritter reopened this May 9, 2023
@mhalbritter mhalbritter added status: waiting-for-triage An issue we've not yet triaged and removed status: invalid An issue that we don't feel is valid labels May 9, 2023
@mhalbritter
Copy link
Contributor

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.

@spring-projects spring-projects deleted a comment from kumarvijay95 May 9, 2023
@spring-projects spring-projects deleted a comment from kumarvijay95 May 9, 2023
@mhalbritter
Copy link
Contributor

mhalbritter commented May 9, 2023

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

@mhalbritter mhalbritter changed the title Invalid RSA private key when using CertBot generated PEM file Can't use PEM encoded EC keys with server.ssl.certificate-private-key May 9, 2023
@mhalbritter mhalbritter added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged labels May 9, 2023
@mhalbritter mhalbritter added this to the 2.7.x milestone May 9, 2023
@mhalbritter
Copy link
Contributor

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.

@mhalbritter mhalbritter changed the title Can't use PEM encoded EC keys with server.ssl.certificate-private-key Can't use PEM encoded PKCS#8 EC keys with server.ssl.certificate-private-key May 9, 2023
@mhalbritter mhalbritter self-assigned this May 9, 2023
@mhalbritter mhalbritter modified the milestones: 2.7.x, 2.7.12 May 9, 2023
@TomerBu
Copy link

TomerBu commented May 9, 2023

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?

@kumarvijay95
Copy link
Author

@mhalbritter when will it be released ??

@wilkinsona
Copy link
Member

@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).

@mhalbritter
Copy link
Contributor

mhalbritter commented May 9, 2023

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.

@philwebb philwebb added the theme: ssl Issues related to ssl support label May 11, 2023
philwebb added a commit that referenced this issue May 12, 2023
Polish and port support for PKCS#8 PEM encoded EC and DSA keys to
the buildpack code.

See gh-35322
@TomerBu
Copy link

TomerBu commented May 14, 2023

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!

@mhalbritter
Copy link
Contributor

Thanks for providing that workaround!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
theme: ssl Issues related to ssl support type: bug A general bug
Projects
None yet
Development

No branches or pull requests

6 participants