Getting Invalid keystore format when running Springboot Application - spring-boot

Trying to use https for my springboot application and followed the below steps:
Created the keystore for the certificate and generated Private Key:
keytool -genkey -keysize 2048 -keyalg RSA -alias tomcat -keystore keystore.jks
Generated the CSR with above keytool and private key
keytool -certreq -alias tomcat -file your.csr -keystore keystore.jks
Recived and install certificate on server succesfully
keytool -import -trustcacerts -alias tomcat -file certificate.p7b -keystore keystore.jks -storepass ******
Configured the application with the below:
server.port=8443
server.ssl.key-store-type=JKS
server.ssl.key-store=/path/certificate.p7b
server.ssl.key-store-password=******
server.ssl.key-alias=tomcat
server.ssl.enabled=true
However I keep getting java.io.IOException: Invalid keystore format when I try to run the application.
Am I using the wrong store key type?
Do I have to use PKCS12 insted of JKS as keystore type?

Related

Kafka Failed SSL Handshake with Springboot

I have successfully setup SSL on Kafka broker, it's listening on port 9093. I'm using consumers built in Springboot, and when I attempt to bring up client consumer, I'm getting the following error:
....
Caused by: org.apache.kafka.common.errors.SslAuthenticationException:
SSL handshake failed Caused by: javax.net.ssl.SSLException:
Unrecognized SSL message, plaintext connection? ...
Below is the configuration on the broker: (server.properties)
listeners=PLAINTEXT://0.0.0.0:9092,SSL://0.0.0.0:9093
advertised.listeners=PLAINTEXT://192.168.xx.xx:9092,SSL://192.168.xx.xx:9093
ssl.keystore.location=/home/kafka/kafka/ssl/kafka.server.keystore.jks
ssl.keystore.password=password
ssl.truststore.location=/home/kafka/kafka/ssl/kafka.server.truststore.jks
ssl.truststore.password=password
ssl.key.password=password
ssl.client.auth=required
This is the configuration on the consumer (Springboot application.properties)
spring.kafka.bootstrap-servers=192.168.xx.xx:9093
spring.kafka.security.protocol=SSL
spring.kafka.ssl.trust-store-location=file:/var/ssl/kafka.client.truststore.jks
spring.kafka.ssl.trust-store-password=password
spring.kafka.ssl.key-store-location=file:/var/ssl/kafka.client.keystore.jks
spring.kafka.ssl.key-store-password=password
spring.kafka.ssl.key-password=password
This is how the keystore/truststore have been created:
CA certificate (root.crt) has signed server.crt and client.crt
kafka.server.keystore.jks contains root.crt, server.crt
kafka.server.truststore.jks contains root.crt
kafka.client.keystore.jks contains root.crt, client.crt
kafka.client.truststore.jks contains root.crt
What could I be missing? Anyone can help?
I have discovered 2 possible causes for this:
Server host name verification: this is likely to fail, so it's best to disabled it by setting ssl.endpoint.identification.algorithm to an empty string in application.properties
i.e.
ssl.endpoint.identification.algorithm=
Keystore generation: this is how I was initially doing it:
i. Generated self signed cert and key (output: ca.key, ca-cert.crt)
ii. Generated server key
and server cert, that was signed by root.crt (output: server.key, server.crt)
iii. Created
keystore by running this command:
keytool -keystore kafka.server.keystore.p12 -storetype PKCS12 -alias CARoot -import -file ca-cert.crt -storepass password -keypass password -noprompt
iv. Imported server.crt into kafka.server.keystore.p12
This will NOT work. This is the right way to do it:
i. Similar to step i above, generate self-signed ca-cert
ii. Generate keystore, that contains server.csr (command in the bash script below)
iii. 'Extract' server.csr, from the keystore generated in step ii, and sign it with ca-cert (output server.crt)
iv. Import ca-cert, and then server.crt into keystore
I decided to do all this in a bash file, so I can do it all in one command. I also preferred PKCS12 format - JKS is proprietory; however, in the configuration you may need to specify key-store-type as PKCS12 [key-store-type=PKCS12]
Here is it:
#!/bin/bash
##
#
# This script generates the following
# server.keystore.p12
# server.truststore.p12
# client.keystore.p12
# client.truststore.p12
# They are self signed, and so CA certificate is created first (ca.key, ca-cert.crt)
#
##
# Server Keystore and Truststore
#====================================
# 1. Generate CA key
openssl genrsa -out ca.key
# 2. Generate CA cert
openssl req -new -x509 -key ca.key -out ca-cert.crt -subj "/C=KE/ST=Kenya/L=Nairobi/O=John Doe Ltd/CN=*.mydomain.com"
# 3. Generate server keystore. A server CSR will be generated automatically
keytool -keystore kafka.server.keystore.p12 -alias serverkey -validity 3650 \
-genkey -keyalg RSA -ext SAN=DNS:*.mydomain.com -storetype PKCS12 -dname "CN=*.mydomain.com, OU=ICT, O=John Doe Ltd, L=Nairobi, ST=Kenya, C=KE" -storepass ****** -keypass ****** -noprompt
# 4. Export server CSR generated in step 3
keytool -keystore kafka.server.keystore.p12 -alias serverkey -certreq -file server.csr -storepass password -noprompt
# 5. Sign the server CSR generated in step 4 with the CA key - output is server.crt
openssl x509 -req -CA ca-root.crt -CAkey ca.key -in server.csr -out server.crt -days 3650 -CAcreateserial
# 6. Import CA cert into the server keystore
keytool -keystore kafka.server.keystore.p12 -alias CARoot -import -file ca-cert.crt -storepass ****** -noprompt
# 7. Import the server cert [generated in step 5] into the keystore
keytool -keystore kafka.server.keystore.p12 -alias serverkey -import -file server.crt -storepass ****** -noprompt
# 8. Generate server truststore and import CA cert
keytool -keystore kafka.server.truststore.p12 -alias CARoot -import -file ca-cert.crt -storepass ****** -noprompt
# Client Keystore and Truststore
#====================================
# 9. Generate client keystore. A client CSR will be generated automatically
keytool -keystore kafka.client.keystore.p12 -alias clientkey -validity 3650 \
-genkey -keyalg RSA -ext SAN=DNS:*.mydomain.com -storetype PKCS12 -dname "CN=*.mydomain.com, OU=ICT, O=ABC Bank Ltd, L=Nairobi, ST=Kenya, C=KE" -storepass ****** -keypass ****** -noprompt
# 10. Export client CSR generated in step 9
keytool -keystore kafka.client.keystore.p12 -alias clientkey -certreq -file client.csr -storepass ****** -noprompt
# 11. Sign the client CSR generated in step 4 with the CA key - output is client.crt
openssl x509 -req -CA ca-cert.crt -CAkey ca.key -in client.csr -out client.crt -days 3650 -CAcreateserial
# 12. Import CA cert into the client keystore
keytool -keystore kafka.client.keystore.p12 -alias CARoot -import -file ca-cert.crt -storepass ****** -noprompt
# 13. Import the client cert [generated in step 11] into the keystore
keytool -keystore kafka.client.keystore.p12 -alias clientkey -import -file client.crt -storepass ****** -noprompt
# 14. Generate client truststore and import CA cert
keytool -keystore kafka.client.truststore.p12 -alias CARoot -import -file ca-cert.crt -storepass ******a -noprompt
This worked perfectly for me. Any comments and corrections are welcome.

SAML HTTPS connection with kennisnet staging environment

I took sample webapp from https://github.com/vdenotaris/spring-boot-security-saml-sample and it is working file. Later. I tried to connect kennisnet staging environment.
Kennisnet details here
https://developers.wiki.kennisnet.nl/index.php?title=KNF:Hoofdpagina/en
I updated metadata which is downloadable from this url https://hub-s.entree.kennisnet.nl/openaselect/profiles/saml2/
I generated smalKeyStore.jks using below commands
keytool -genkey -alias tomcat -keyalg RSA -keystore samlKeyStore.jks
keytool -importkeystore -srckeystore samlKeyStore.jks -destkeystore
samlKeyStore.jks -deststoretype pkcs12
I followed all Spring SAML https threads in stackoverflow and not able to figure it out this issue.
LOGS:
Add the certificate to your JDK so that your application can get the metadata from URL https://aselect-s.entree.kennisnet.nl/openaselect/profiles/saml2.
These are the steps you need to fillow:
Download the certificate for aselect-s.entree.kennisnet.nl
Import the certificate to your JDK/JRE using this command:
keytool -keystore #path to java_home#/lib/security/cacerts -importcert -alias #anything relevent# -file #path to certificate#
Make sure your server is using same java_home where you are importing the certificate, also verify the subjectname in the certificate before importing, it must be "CN = *.entree.kennisnet.nl"
Restart the server.

ssl setup in embedded tomcat Spring boot

I have a ssl certicate provided by globalsign. I want to import the certificate to use it with tomcat.
I am doing the following operation
Importing chain certificate
keytool -import -alias root11 -keystore server11.p12 -trustcacerts -file chain.pem -keyalg RSA -keysize 2048 -storetype PKCS12
Importing certificate
keytool -import -alias tomcatroot11 -keystore server11.p12 -trustcacerts -file file.cert -keyalg RSA -keysize 2048 -storetype PKCS12
In application.properties
server.ssl.key-store= /Users/Desktop/certificate/server11.p12
server.ssl.key-store-password= password
server.ssl.keyStoreType= PKCS12
server.ssl.keyAlias= tomcatroot11
I am getting the following error on start up of tomcat
java.lang.IllegalArgumentException: java.io.IOException: Alias name [hcmroot11] does not identify a key entry
at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:114) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
What am i doing wrong?
You have imported only the certificates, not any privatekey. SSL/TLS server needs a privatekey AND certficate or usually cert chain. See dupe Java SSLHandshakeException: no cipher suites in common (which has additional links) or crossdupe https://serverfault.com/questions/858102/jboss-https-configuration-with-cer-p7b-certificate-fails (the webserver component of Jboss is a fork of Tomcat).
-keyalg and -keysize are used only for -genkeypair, if you choose the approach of generating the key and (then) CSR in Java with keytool. They are useless and ignored on -importcert because it is impossible to modify any attribute(s) of an already-certified key.

keytool asks for password despite -noprompt and -keypass is set

I'm trying to create an installation script, that reads data out of an .ini file and writes it into several configuration files. One step is to create an SSL key via keytool and to request it's certification (create a csr-file). I now have the problem that keytool asks for the password instead of using the provided one (in the variable $keyStorePassword), although i also have activated -noprompt. I would be glad if anyone could help.
keytool -genkey -noprompt -keyalg RSA -keysize 2048 \
-dname "CN=${HOSTNAME}-${microserviceName}-${environment}, O=${organizationName}, L=${localityName}, S=${stateName}, C=${country}" \
-validity ${validity} -keypass ${keyStorePassword} -keystore ${keyStorePath} -alias ${microserventerviceName}-ssl
keytool -certreq -keyalg RSA -file ${microserviceName}.csr -keystore ${keyStorePath} -alias ${microserviceName}-ssl
I've already searched the web but the problem doesn't seem to be common.
There are two parameters for passwords:
-keypass: The password for the key.
-storepass: The password for the keystore.
Each key entry in a Java keystore has its individual password, so you have to provide both the keystore password and the key password when generating a new key or accessing a key.

Jetty - SSL Websocket Client

I have a websocket server (API of jetty 9.0.1.v20130408), which worked fine without ssl. Now I configured my server like this:
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath("/src/main/resources/keystore.jks");
sslContextFactory.setKeyStorePassword(password);
sslContextFactory.setTrustStorePath("/src/main/resources/truststore.jks");
sslContextFactory.setTrustStorePassword(password);
ConnectionFactory sslConnFactory = new SslConnectionFactory(sslContextFactory, "http/1.1);
connector.addConnectionFactory(sslConnFactory);
server.addConnector(connector);
No I tried to configurate the client. I thought, that on the client side I need to set path to truststore.jks and the password. But then I get on client.start() the Exception: SSL doesn't have a valid keystore. When I set the keystore, then I get on client.connect java.nio.channels.WritePendingException. Here is the code for my client:
WebSocketClient client = new WebSocketClient(sslContextFactory);
URI wssUri = new URI("wss://localhost:"+port);
sslContextFactory.start();
client.start();
client.connect(myClientSocket, wssUri);
Can anybody help me? I also tried on server side to set setWantClientAuth(false) and setTrustall(true), but it also did not work this way;
ADDED:
I generate my ssl files with keytool.
$ keytool -genkeypair -alias certificatekey -keyalg RSA -validity 365 -keystore keystore.jks
$ keytool -export -alias certificatekey -keystore keystore.jks -rfc -file selfsignedcert.cer
$ keytool -import -alias certificatekey -file selfsignedcert.cer -keystore truststore.jks
This is because UpgradeRequest is sent twice, as reported here
You can ignore the warning for now. Just use 9.0.4 when it is released.

Resources