24

I'm following this tutorial to enable HTTPS in Spring Boot 2.0 using a self-signed certificate, just for testing purpose. In summary, that tutorial includes these steps:

1.Generate the keystore using keytool.

keytool -genkey -alias tomcat
 -storetype PKCS12 -keyalg RSA -keysize 2048
 -keystore keystore.p12 -validity 3650

2.Enable HTTPS in Spring Boot by adding some properties in the application.properties file.

server.port: 8443
server.ssl.key-store: keystore.p12
server.ssl.key-store-password: mypassword
server.ssl.keyStoreType: PKCS12
server.ssl.keyAlias: tomcat

3.Redirect HTTP to HTTPS (optional). I ignored this part.

But when I start my application, I got these error:

org.apache.catalina.LifecycleException: Failed to start component [Connector[HTTP/1.1-8443]]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.catalina.core.StandardService.addConnector(StandardService.java:225) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.addPreviouslyRemovedConnectors(TomcatWebServer.java:255) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start(TomcatWebServer.java:197) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.startWebServer(ServletWebServerApplicationContext.java:300) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:162) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:552) [spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:388) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:327) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1246) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1234) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at epic.gwdg.restgraph.RestgraphApplication.main(RestgraphApplication.java:10) [classes/:na]
Caused by: org.apache.catalina.LifecycleException: Protocol handler start failed
    at org.apache.catalina.connector.Connector.startInternal(Connector.java:1021) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    ... 13 common frames omitted
Caused by: java.lang.IllegalArgumentException: Private key must be accompanied by certificate chain
    at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:116) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.tomcat.util.net.AbstractJsseEndpoint.initialiseSsl(AbstractJsseEndpoint.java:87) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:225) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.tomcat.util.net.AbstractEndpoint.start(AbstractEndpoint.java:1150) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.coyote.AbstractProtocol.start(AbstractProtocol.java:591) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.catalina.connector.Connector.startInternal(Connector.java:1018) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    ... 14 common frames omitted
Caused by: java.lang.IllegalArgumentException: Private key must be accompanied by certificate chain
    at java.base/java.security.KeyStore.setKeyEntry(KeyStore.java:1170) ~[na:na]
    at org.apache.tomcat.util.net.jsse.JSSEUtil.getKeyManagers(JSSEUtil.java:257) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:114) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    ... 19 common frames omitted

2018-03-16 16:42:30.917  INFO 970 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
2018-03-16 16:42:30.931  INFO 970 --- [           main] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2018-03-16 16:42:30.933 ERROR 970 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

The Tomcat connector configured to listen on port 8443 failed to start. The port may already be in use or the connector may be misconfigured.

Action:

Verify the connector's configuration, identify and stop any process that's listening on port 8443, or configure this application to listen on another port.

2018-03-16 16:42:30.934  INFO 970 --- [           main] ConfigServletWebServerApplicationContext : Closing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@58ce9668: startup date [Fri Mar 16 16:42:26 CET 2018]; root of context hierarchy
2018-03-16 16:42:30.936  INFO 970 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown

Process finished with exit code 1

Basically, the message is:

Private key must be accompanied by certificate chain.

This is a self-signed certificate, so it, of course, doesn't have the trusted chain. How can I fix it?

Here is my current application.properties file:

server.port=8443
server.ssl.enabled=true
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-password=123456
server.ssl.key-store-type=PKCS12
server.ssl.key-alias=tomcat

Thank you so much for your help.

Triet Doan
  • 11,455
  • 8
  • 36
  • 69

7 Answers7

23

The problem is that in your generated keystore you dont have a key pair so there is no private key that's because your using the option -genkey you need to change it by the option -genkeypair :

-genkey generates a Secret Key whereas the -genkeypair generates a key pair (a public key and a private key).

So I think this should work :

keytool -genkeypair -alias tomcat -storetype PKCS12 -keyalg RSA -keysize 2048  -keystore keystore.p12 -validity 3650

In your spring boot configuration change ":" by "=" and add the path to your keystore I suppose that your keystore.p12 is in your resources folder so :

server.ssl.key-store = classpath:keystore.p12
server.ssl.key-store-password = mypassword
server.ssl.key-store-type = PKCS12
server.ssl.key-alias = tomcat
e2rabi
  • 4,728
  • 9
  • 42
  • 69
  • Thanks, but I still have the same problem :( – Triet Doan Mar 16 '18 at 16:15
  • I update my response ,in your spring properties conf change " : " by "=" and add the path to your keystore for the param "server.ssl.key-store" – e2rabi Mar 16 '18 at 16:34
  • In fact, I use "=" and "classpath" in my configuration. I tried both way and the error is still there... – Triet Doan Mar 16 '18 at 16:36
  • I update my response again there is an other problem again change "server.ssl.keyStoreType" = PKCS12 by "server.ssl.key-store-type=PKCS12" – e2rabi Mar 16 '18 at 16:40
  • 6
    I just updated my question to add my configuration. I notice that the password field should be `key-store-password`, like yours. I changed it, and it works!!! You can update your answer (`key-alias`). I will mark your answer as correct. Thank you :) – Triet Doan Mar 16 '18 at 19:45
  • 1
    My application doesn't give me exception, but via http the browser says `Bad Request This combination of host and port requires TLS` and via https says `NET::ERR_CERT_AUTHORITY_INVALID` What should I do then? – tibotka Nov 20 '20 at 15:21
10

I was getting this horrible Private key must be accompanied by certificate chain error as well on my Spring Boot application with an embedded Tomcat server. It was making me insane.

It turns out a simple typo was my problem:

@Override
public void customize(ConfigurableServletWebServerFactory server) {
    Ssl ssl = new Ssl();
    ssl.setEnabled(true);
    ssl.setKeyStore(keystoreFile);
    ssl.setKeyPassword(keystorePass); // << Should be `setKeyStorePassword` !!!!
    ssl.setKeyStoreType(keystoreType);
    ssl.setKeyAlias(keystoreAlias);

    server.setSsl(ssl);
    server.setPort(sslPort);
}

So the error message is not helpful at all for this case. I hope this helps someone else. Just be sure to verify that you're putting the right passwords (key vs keystore) in the right place. The same issue can happen in a properties based setup - it depends on what you are working with.

jocull
  • 20,008
  • 22
  • 105
  • 149
7

You made a small mistake in the application.properties file. Please change

server.ssl.key-password=your_password

to

server.ssl.key-store-password=your_password

It will work fine then. Hope it helps! Thank you!

Arun Kumar N
  • 1,611
  • 1
  • 20
  • 25
  • Thank you, only this change solved my issue. Still don't know why cause I had another self-signed certification and with `server.ssl.key-password=your_password` worked... – Renan Ribeiro Mar 04 '21 at 18:44
3

I had a similar problem, in my case i was missing the trustAnchors in the trust store.

One solution is to use the java built-in keytool, like explained in the other answers. But there is an even simplest approach using KeyStore Explorer GUI, so i'll explain the complete steps with both tools.

1. First of all, as described in the answer, we need to enable SSL in the application.properties file:

# <======= SSL Security ===========>
# Keystore config
server.ssl.key-store-type=PKCS12
server.ssl.key-store-password=change_it!
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-alias=alias
server.ssl.enabled=true

# Trust Store Certificates
server.ssl.trust-store=classpath:trust_store.p12
server.ssl.trust-store-type=PKCS12
server.ssl.trust-store-password=07123e1f482356c415f684407
# <=====================>

The Keystore is the container of the Public - Private Key pair that is used by the server to communicate securely with the clients. The client of course must have the Public Key to be able to communicate with the server.

The Trust Store is simply a container for the certificates. (the Public Keys). In our case it will contain only one certificate, the one used by the server.

2.1 Create the keystore with the java keytool:

keytool -genkeypair -alias alias -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore keystore.p12 -validity 3650

2.2 Export the certificate so we can use it to create the Trust Store Keystore

keytool -export -keystore keystore.p12 -alias alias -file certificate.cer

2.3 This step will automatically create a new keystore with the imported trusted certificate. (The tool will ask you a password for the new keystrore and when it asks "Trust this certificate?" of course you should type "yes")

keytool -importcert -file certificate.cer -keystore trust_store.p12 -alias alias

Finally save both keystores inside the resources folder of your Spring Boot App (as shown in the alternative approach).

Alternative approach with KeyStore Explorer

2.1 Create the keystore with the KeyStore Explorer, as shown in the screenshots: enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here

Then save the keystore inside the resources folder of your Spring Boot App: enter image description here

2.2 Now we need to create the trust store, that can be given to the client that needs to communicate with our server. First of all extract the certificate chain created by the KeyStore Explorer and then create a new KeyStore importing the certificate inside it, as shown in the screenshots:

enter image description here enter image description here enter image description here

Then to create our trust store, click on "Create a new KeyStore" with the PKCS12 format as in the previous steps, the click the red icon "Import trusted certificate", choose the certificate saved in the preceding step, and finally save the keystore inside the resources folder like we did in the first keystore creation.

Now your server will be enabled to communicate with SSL security. Remember that your clients must be configured to load the trust store you've created .

Domenico
  • 1,331
  • 18
  • 22
2

1.use " -genkeypair"

keytool -genkeypair -alias tomcat -storetype PKCS12 -keyalg RSA -keysize 2048  -keystore keystore.p12 -validity 3650
  1. change "server.ssl.key-password" to "server.ssl.key-store-password"
Frank Liu
  • 21
  • 1
  • 1
    +1 for the second part. I think there was some renaming in a later Springboot version, but sadly the error message doesn't say anything about not being able to correctly read the password. – Aaron Cooley Feb 21 '19 at 21:24
1

Spring Boot 2.2.1.RELEASE

keytool -genkeypair -keystore myKeystore2.p12 -storetype PKCS12 -storepass 123456 -alias ks-localhost -keyalg RSA -keysize 2048 -validity 99999 -dname "CN=My SSL Certificate, OU=My Team, O=My Company, L=My City, ST=My State, C=SA" -ext san=dns:localhost,ip:127.0.0.1

application.yml

server:
  tomcat:
    accesslog:
      enabled: true
  ssl:
    key-store-type: PKCS12
    key-store: classpath:myKeystore.p12
    key-alias: ks-localhost
    enabled: true
    protocol: TLS
    key-store-password: 123456
maestr0
  • 5,318
  • 3
  • 28
  • 27
0

I had the same problem. I made the changes from 2nd answer. But problem wasn't gone. After all I've made, I just included my keystore.p12 certificate to pom.xml in profiles section

    <profiles>
    <!-- DEVELOPMENT PROFILE -->
    <profile>
        <id>dev</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <build>
            <resources>
                <resource>
                    <directory>src/main/resources</directory>
                    <includes>
                        <include>application.properties</include>
                        <include>keystore.p12</include>
                        <include>data/**</include>
                    </includes>
                </resource>
            </resources>
        </build>
    </profile>
</profiles>
JenkaBY
  • 911
  • 5
  • 5