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

Tomcat fails to start when PEM files are used and key-store-password is not specified #31253

Closed
AlexElin opened this issue Jun 5, 2022 · 5 comments
Assignees
Labels
type: bug A general bug
Milestone

Comments

@AlexElin
Copy link

AlexElin commented Jun 5, 2022

Spring Boot: 2.7.0

Web Server fails to start when PEM files with not password-protected key are used and key-store-password is not specified.
However if any password is set in key-store-password, the app starts successfully.

My expected behavior is that app start successully without key-store-password

Exception's stacktrace

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2022-06-05 12:02:21.014 ERROR 16904 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.context.ApplicationContextException: Failed to start bean 'webServerStartStop'; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat server
	at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:181) ~[spring-context-5.3.20.jar:5.3.20]
	at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:54) ~[spring-context-5.3.20.jar:5.3.20]
	at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:356) ~[spring-context-5.3.20.jar:5.3.20]
	at java.base/java.lang.Iterable.forEach(Iterable.java:75) ~[na:na]
	at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:155) ~[spring-context-5.3.20.jar:5.3.20]
	at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:123) ~[spring-context-5.3.20.jar:5.3.20]
	at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:935) ~[spring-context-5.3.20.jar:5.3.20]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:586) ~[spring-context-5.3.20.jar:5.3.20]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.0.jar:2.7.0]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) ~[spring-boot-2.7.0.jar:2.7.0]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) ~[spring-boot-2.7.0.jar:2.7.0]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[spring-boot-2.7.0.jar:2.7.0]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.0.jar:2.7.0]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.0.jar:2.7.0]
	at com.example.demo.DemoApplication.main(DemoApplication.java:10) ~[classes/:na]
Caused by: org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat server
	at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start(TomcatWebServer.java:229) ~[spring-boot-2.7.0.jar:2.7.0]
	at org.springframework.boot.web.servlet.context.WebServerStartStopLifecycle.start(WebServerStartStopLifecycle.java:43) ~[spring-boot-2.7.0.jar:2.7.0]
	at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:178) ~[spring-context-5.3.20.jar:5.3.20]
	... 14 common frames omitted
Caused by: java.lang.IllegalArgumentException: standardService.connector.startFailed
	at org.apache.catalina.core.StandardService.addConnector(StandardService.java:238) ~[tomcat-embed-core-9.0.63.jar:9.0.63]
	at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.addPreviouslyRemovedConnectors(TomcatWebServer.java:282) ~[spring-boot-2.7.0.jar:2.7.0]
	at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start(TomcatWebServer.java:213) ~[spring-boot-2.7.0.jar:2.7.0]
	... 16 common frames omitted
Caused by: org.apache.catalina.LifecycleException: Protocol handler start failed
	at org.apache.catalina.connector.Connector.startInternal(Connector.java:1075) ~[tomcat-embed-core-9.0.63.jar:9.0.63]
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) ~[tomcat-embed-core-9.0.63.jar:9.0.63]
	at org.apache.catalina.core.StandardService.addConnector(StandardService.java:234) ~[tomcat-embed-core-9.0.63.jar:9.0.63]
	... 18 common frames omitted
Caused by: java.lang.IllegalArgumentException: Get Key failed: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
	at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:107) ~[tomcat-embed-core-9.0.63.jar:9.0.63]
	at org.apache.tomcat.util.net.AbstractJsseEndpoint.initialiseSsl(AbstractJsseEndpoint.java:71) ~[tomcat-embed-core-9.0.63.jar:9.0.63]
	at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:234) ~[tomcat-embed-core-9.0.63.jar:9.0.63]
	at org.apache.tomcat.util.net.AbstractEndpoint.bindWithCleanup(AbstractEndpoint.java:1227) ~[tomcat-embed-core-9.0.63.jar:9.0.63]
	at org.apache.tomcat.util.net.AbstractEndpoint.start(AbstractEndpoint.java:1313) ~[tomcat-embed-core-9.0.63.jar:9.0.63]
	at org.apache.coyote.AbstractProtocol.start(AbstractProtocol.java:614) ~[tomcat-embed-core-9.0.63.jar:9.0.63]
	at org.apache.catalina.connector.Connector.startInternal(Connector.java:1072) ~[tomcat-embed-core-9.0.63.jar:9.0.63]
	... 20 common frames omitted
Caused by: java.security.UnrecoverableKeyException: Get Key failed: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
	at java.base/sun.security.pkcs12.PKCS12KeyStore.engineGetKey(PKCS12KeyStore.java:450) ~[na:na]
	at java.base/sun.security.util.KeyStoreDelegator.engineGetKey(KeyStoreDelegator.java:91) ~[na:na]
	at java.base/java.security.KeyStore.getKey(KeyStore.java:1050) ~[na:na]
	at org.apache.tomcat.util.net.SSLUtilBase.getKeyManagers(SSLUtilBase.java:354) ~[tomcat-embed-core-9.0.63.jar:9.0.63]
	at org.apache.tomcat.util.net.SSLUtilBase.createSSLContext(SSLUtilBase.java:247) ~[tomcat-embed-core-9.0.63.jar:9.0.63]
	at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:105) ~[tomcat-embed-core-9.0.63.jar:9.0.63]
	... 26 common frames omitted
Caused by: javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
	at java.base/com.sun.crypto.provider.CipherCore.unpad(CipherCore.java:859) ~[na:na]
	at java.base/com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:939) ~[na:na]
	at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:735) ~[na:na]
	at java.base/com.sun.crypto.provider.PBES2Core.engineDoFinal(PBES2Core.java:325) ~[na:na]
	at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2205) ~[na:na]
	at java.base/sun.security.pkcs12.PKCS12KeyStore.lambda$engineGetKey$0(PKCS12KeyStore.java:371) ~[na:na]
	at java.base/sun.security.pkcs12.PKCS12KeyStore$RetryWithZero.run(PKCS12KeyStore.java:257) ~[na:na]
	at java.base/sun.security.pkcs12.PKCS12KeyStore.engineGetKey(PKCS12KeyStore.java:361) ~[na:na]
	... 31 common frames omitted

application.yml

server:
  port: 8443
  http2:
    enabled: true
  compression:
    enabled: true
  ssl:
    enabled: true
    certificate: classpath:test-cert-chain.pem
    certificate-private-key: classpath:test-key.pem
#    key-store-password: anything # If it's commented out, the server doesn't start. Otherwise it starts with any password specified

Certificare and prvvate key are test-cert-chain.pem and test-key.pem .

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>demo</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

DemoApplication.java

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jun 5, 2022
@wilkinsona
Copy link
Member

Thanks for the report. The problem is due to different defaults in Spring Boot and Tomcat when no password is configured.

In Spring Boot, the entry is added to the in-memory KeyStore with an empty (zero character) password:

if (privateKey != null) {
keyStore.setKeyEntry(alias, privateKey, ((password != null) ? password.toCharArray() : NO_PASSWORD),
certificates);
}

In Tomcat, the default password for retrieving the key from the store is "changeit".

It works when you configure any password as the entry is added to the store with that password and Tomcat then uses that same password when retrieving the key from the store.

Jetty, Netty, and Undertow don't seem to be affected.

@wilkinsona wilkinsona added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged labels Jun 6, 2022
@wilkinsona wilkinsona added this to the 2.7.x milestone Jun 6, 2022
@wilkinsona wilkinsona changed the title Web Server fails to start when PEM files with not password-protected key are used and key-store-password is not specified Tomcat fails to start when PEM files are used and key-store-password is not specified Jun 6, 2022
@shaheryarshakeel
Copy link

@wilkinsona Hi, can I please work on it?

Kindly share if there is any other helpful insight with regards to this issue.

@wilkinsona
Copy link
Member

Thanks for the offer, @shaheryarshakeel, but I already have a possible fix for this that I have been discussing with @scottfrederick.

@wilkinsona wilkinsona self-assigned this Jun 7, 2022
@shaheryarshakeel
Copy link

@wilkinsona Please let me know if I can help in any way, I genuinely wants to tap into open source contributions and there is no place better than spring which I use everyday, thanks

@wilkinsona
Copy link
Member

Thanks for the offer, @shaheryarshakeel. Please keep an eye out for issues that are labeled as ideal for contribution.

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

No branches or pull requests

4 participants