Tag Archives: java - Page 7

SSLHandshakeException: unable to find valid certification path to requested target

You are trying to connect to a server over SSL and you get the following error:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.ssl.Alerts.getSSLException(Alerts.java:198)
	at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1967)
...

This means that your computer does not trust the remote computer. The remote computer serves a certificate that your computer is unable to find a trusted source for. Could be that the remote certificate is selfsigned or uses a CA that you computer does not know

One solution: Add the remote computers certificate into your truststore:
1. Get the remote computer certificate using OpenSSL:

openssl s_client -connect <remote computer adress> <remote computer port>

This will present the remote computers certificate (BEGIN CERTIFICATE to END CERTIFICATE). Copy this to a file (Preserve BEGIN and END rows)
2. Add the remote certificate to your java truststore

sudo keytool -import -alias remote_computer_cert -file <remote computer cert> -keystore /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/security/cacerts

3. Done – connect again – the error should be gone

Tested on OSX v10.15.6, OpenSSL 2.8.3 (LibreSSL) and Java 1.8.0_252 (OpenJDK)

My Java Keytool cheat sheet

# List all entries in a JKS
keytool -list -keystore mykeystore.jks -storepass changeit

# List all entries in a PKCS12
keytool -list -keystore mykeystore.jks -storepass changeit -storetype pkcs12

# List detailed information about all entries in a JKS
keytool -list -v -keystore mykeystore.jks -storepass changeit

# Rename an alias in a JKS
keytool -changealias -alias "client01" -destalias "client02" -keystore mykeystore.jks -storepass changeit

# Remove an alias in a JKS
keytool -delete -alias "client01" -keystore mykeystore.jks -storepass changeit

# Create a JKS with a self-signed certificate
keytool -genkey -keyalg RSA -alias client01 -keystore mykeystore.jks -storepass changeit -validity 365 -keysize 2048

# Create a JKS and import certificate from file (if keystore does not exist it will be created)
keytool -keystore mykeystore.jks -storepass changeit -import -file mycertfile.crt

# Import a certificate to trust to a jks
keytool -import -alias server01 -file server01.crt -keystore mykeystore.jks

# Change JKS keystore password
keytool -storepasswd -keystore mykeystore.jks

# Change a JKS key's password:
keytool -keypasswd  -alias <key_name> -keystore mykeystore.jks

# Extract certificate from a jks keystore
keytool -export -keystore mykeystore.jks -alias client01 -file client01.crt

# Convert a PKCS12 (p12) certificate to JKS
keytool -importkeystore  
  -srckeystore mysourcekeystore.p12 
  -destkeystore mydestkeystore.jks 
  -srcstoretype PKCS12 
  -deststoretype JKS 
  -srcstorepass mysourcepassword 
  -deststorepass mydestpassword 
  -srcalias mysourcecertalias 
  -destalias mydetscertalias 
  -srckeypass mysourcekeypassword 
  -destkeypass mydestkeypassword

# Convert a JKS keystore to a PKCS12 keystore
keytool -importkeystore 
  -srckeystore mykeystore.jks 
  -destkeystore mykeystore.p12
  -deststoretype pkcs12 

# Generate a self-signed certificate and put it into a JKS (valid for 720 days)
keytool -genkey 
  -keyalg RSA 
  -alias server 
  -keystore selfsigned.jks 
  -validity 720 
  -keysize 2048

Tested on Red Hat 7 and Java 8

My Play Framework Systemd script

Ubuntu deprecated Upstart so I had to turn to Systemd for my app controls in Ubuntu 18.04. In this script I set 2 environment variables (HOME and LANG), change directory to the app directory and starts the Play Framework application

# Myapp systemd script
#
# Location:/lib/systemd/system/myapp.service
#
# Useful commands:
#
# Start Myapp: 		systemctl start myapp.service
# Stop Myapp:		systemctl stop myapp.service
# Restart Myapp:	systemctl restart myapp.service
# Show status:		systemctl status myapp.service
# Enable start on boot:	systemctl enable myapp.service
# Disable start on boot:systemctl disable myapp.service
#
# List all services running: systemctl
# Check config: systemd-analyze verify myapp.service
#
####################################################################################

[Unit]
Description=Job that runs my app daemon

[Service]
Type=forking
Environment=HOME=/opt/myapp/app
Environment=LANG=en_US.UTF-8
ExecStartPre=/bin/bash -c 'cd /opt/myapp/app'
ExecStart=/bin/bash -c 'bin/myapp -J-Xms256M -J-Xmx768m -J-server -Dhttp.port=80 -Dconfig.file=conf/application.conf -Dlogger.file=conf/application-logger.xml'

[Install]
WantedBy=multi-user.target

The arguments for the Play service are what I normally use for AWS. You might need other settings

Tested on Ubuntu 18.04 and Play Framework 2.3