November 2024
M T W T F S S
 123
45678910
11121314151617
18192021222324
252627282930  

Categories

November 2024
M T W T F S S
 123
45678910
11121314151617
18192021222324
252627282930  

Tomcat could not run through SSL due to jsse.invalid_ssl_conf

SEVERE: Error initializing endpoint
java.io.IOException: jsse.invalid_ssl_conf
    at org.apache.tomcat.util.net.jsse.JSSESocketFactory.checkConfig(JSSESocketFactory.java:817)
    at org.apache.tomcat.util.net.jsse.JSSESocketFactory.init(JSSESocketFactory.java:522)
    ...
Caused by: javax.net.ssl.SSLException: No available certificate or key corresponds to the SSL cipher suites which are enabled.
    at com.sun.net.ssl.internal.ssl.SSLServerSocketImpl.checkEnabledSuites(SSLServerSocketImpl.java:310)
    at com.sun.net.ssl.internal.ssl.SSLServerSocketImpl.accept(SSLServerSocketImpl.java:255)
    at org.apache.tomcat.util.net.jsse.JSSESocketFactory.checkConfig(JSSESocketFactory.java:813)
    ...
SEVERE: Failed to initialize connector [Connector[HTTP/1.1-8443]]
LifecycleException:  Protocol handler initialization failed: java.io.IOException: jsse.invalid_ssl_conf
    at org.apache.catalina.connector.Connector.initialize(Connector.java:1024)
    at org.apache.catalina.core.StandardService.initialize(StandardService.java:703)
    ...

Cause

This error might be caused of certain things such as, the keystoretype is not defined in server.xml thus the JSSE could not recognized the keystore as the keystore is not on default type which is JKS. Other thing is the certificate has not be imported to keystore that is generated by  keytool as it does not let you import an existing private key for which you already have a certificate.

Resolution

  1. You need to define the keystoreType to server.xml as the default one is JKS. For example under your server.xml would become like this.

    <Connector port="8443" maxHttpHeaderSize="8192"
                       maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
                       enableLookups="false" disableUploadTimeout="true"
                       acceptCount="100" scheme="https" secure="true"
                       clientAuth="false" sslProtocol="TLS" SSLEnabled="true"
                       URIEncoding="UTF-8" keystorePass="<MY_CERTIFICATE_PASSWORD>"
                       keystoreFile="<MY_CERTIFICATE_LOCATION>" keystoreType="PKCS12"/> 

 

Import private key and certificate into Java Key Store (JKS)

Apache Tomcat and many other Java applications expect to retrieve SSL/TLS certificates from a Java Key Store (JKS). Jave Virtual Machines usually come with keytool  to help you create a new key store.

Keytool helps you to:

  • create a new JKS with a new private key
  • generate a Certificate Signung Request (CSR) for the private key in this JKS
  • import a certificate that you received for this CSR into your JKS

Keytool does not let you import an existing private key for which you already have a certificate. So you need to do this yourself, here’s how:

Let’s assume you have a private key (key.pem) and a certificate (cert.pem), both in PEM format as the file names suggest.

PEM format is ‘kind-of-human-readable’ and looks like e.g.

-----BEGIN CERTIFICATE-----
Ulv6GtdFbjzLeqlkelqwewlq822OrEPdH+zxKUkKGX/eN
.
. (snip)
.
9801asds3BCfu52dm7JHzPAOqWKaEwIgymlk=
----END CERTIFICATE-----

Convert both, the key and the certificate into DER format using openssl :

openssl pkcs8 -topk8 -nocrypt -in key.pem -inform PEM -out key.der -outform DER
openssl x509 -in cert.pem -inform PEM -out cert.der -outform DER

Now comes the tricky bit, you need something to import these files into the JKS. ImportKey will do this for you, get the ImportKey.java (text/x-java-source, 6.6 kB, info) source or the compiled (Java 1.5 !) ImportKey.class (application/octet-stream, 3.3 kB,info) and run it like[gview file=”http://rmohan.com/wp-content/uploads/2014/05/ImportKey.zip”]

user@host:~$ java ImportKey key.der cert.der
Using keystore-file : /home/user/keystore.ImportKey
One certificate, no chain.
Key and certificate stored.
Alias:importkey  Password:importkey

Now we have a proper JKS containing our private key and certificate in a file called keystore.ImportKey, using ‘importkey’ as alias and also as password. For any further changes, like changing the password we can use keytool.

  1. Convert your private key and certificate from the PEM format into DER (PKCS8, not PKCS12):
    openssl pkcs8 -topk8 -nocrypt -in myhost.key -inform PEM -out myhost.key.der -outform DER
    openssl x509 -in myhost.crt -inform PEM -out myhost.crt.der -outform DER
  2. Modify the ImportKey.java to set a passphrase for the keystore and an alias to access your certificate.
  3. Compile it into a class file:
    javac ImportKey.java
  4. Run it to import your key and certificate:
    java ImportKey myhost.key.der myhost.crt.der

The application then creates a file keystore.ImportKey which holds a combination of your certificate and private key that you can put into your application directory, e.g. underconf/keystore.

You do not need to add any intermediate certificate authorities to the keystore.

Set up your server.xml

You are now ready to use your certificate. Modify your server.xml inside the application directory and add a Connector entry like this:

<Connectorport="8443"maxHttpHeaderSize="8192"maxThreads="150"minSpareThreads="25"maxSpareThreads="75"enableLookups="false"disableUploadTimeout="true"acceptCount="100"scheme="https"secure="true"clientAuth="false"sslProtocol="TLS"SSLEnabled="true"URIEncoding="UTF-8"keystorePass="secret123456"keystoreFile="conf/keystore"keyAlias="private_key"/>
  • Providing the keystoreFile and keystorePass (the password you chose above) tells the application how to access the keystore.
    If you encountered the “java.io.IOException: jsse.invalid_ssl_conf” exception before, this is most likely the answer to it.
  • Setting the keyAlias (you put it into the ImportKey.java) hints which key to use.
    If you got an exception like “java.io.IOException: Alias name foobar does not identify a key entry” you were providing an existing name but only a certificate without a private key.
  • You can also modify those settings later by using the corresponding keytool commands.

Now you should be able to restart your application and access it via SSL on port 8443. If it does not come up (maybe only listening on non-SSL ports) check the logs for any of the above exceptions.

Important: Remove any world and group permissions on the server.xml to keep your passphrase hidden from other users/applications on the server. You may want to chmod your keystore, too.

chmod g-rwx,o-rwx server.xml keystore

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>