🛡️ Using Self-Signed Certificates with Java-Based Applications

Java applications often rely on TLS for secure communication. However, when IT organizations issue self-signed or internally signed SSL certificates, these certificates typically aren't recognized by Java's default trust store. This can result in SSL handshake errors like:

PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: 
unable to find valid certification path to requested target

This article explores the root cause of this issue, walks through solutions across Windows and Linux environments, and covers how to integrate trusted certs into Docker images—specifically for OpenLegacy’s openlegacy/hub-enterprise:latest.


⚠️ The Problem: Untrusted Certificates

When Java initiates an SSL/TLS connection, it verifies the server's certificate against its trust store (cacerts). If your Java application accesses a server with a self-signed certificate or one issued by an internal CA, Java will reject the connection unless the certificate is added to the trust store.


🧰 Solution Overview

The solution involves importing the relevant certificate chain—ideally starting from the root CA or intermediate CA certificate—into the Java trust store. This allows Java to properly validate the server certificate against a known issuer

Important: Don’t just grab the server’s public certificate. You’ll need the Certificate Authority (CA) certificate that issued it (either the root CA or intermediate CA). This is what Java needs to trust the server and build a complete certification path

Step 1: Export the Certificate

🏢 Exporting CA Certificate from Internal Certificate Authority (e.g., Windows CA Server)

If your organization uses an internal Microsoft CA:

  • Open Certificate Authority Management Console on the CA server:

    • Run certsrv.msc or open via Server Manager.
  • Go to the Certification Authority Root Node:

    • This displays the CA name (e.g., Corp-CA).
  • Right-click the CA Name → All Tasks → Export CA Certificate:

    • Choose to export as Base64 encoded X.509 (.CER).
  • Save the.cer file to a location accessible to you.


🌐 Exporting CA from Browser (if already trusted)

If you're connecting to a server that’s already trusted by your browser:

In Chrome or Edge:

  • Navigate to the secure site (e.g., https://internal-server).
  • Click the padlock icon → Certificate → Certification Path.
  • Select the top-level certificate in the path (this is the CA).
  • Click "View Certificate" → "Details" → "Copy to File".
  • Choose Base64 encoded X.509 (.CER) and export.

🔍 Exporting CA from Server Using OpenSSL

If you’re accessing an internal service and you don’t have GUI access:

openssl s_client -connect server.domain.com:443 -showcerts
  • You’ll see the full certificate chain.
  • Copy the top-most certificate block (-----BEGIN CERTIFICATE----- ...).
  • Save it as ca-cert.pem.

You can also inspect and verify with:

openssl x509 -in ca-cert.pem -text -noout

Look for Issuer and Subject—they’ll often be the same for a self-signed CA.


🖥️ Adding Certificate on Windows (Local Java Environment)

Step 2: Locate the Java cacerts Trust Store

Default location:

C:\Program Files\Java\jdk<version>\lib\security\cacerts

Step 3: Import the Certificate

Open Command Prompt as administrator and run:

keytool -import -alias customcert -keystore "C:\Program Files\Java\jdk<version>\lib\security\cacerts" -file customcert.pem
  • Default password: changeit
  • You’ll be asked to confirm the certificate trust.

🐧 Adding Certificate on Linux-Based Server

Locate Java cacerts (common paths)

/usr/lib/jvm/java-<version>/lib/security/cacerts

Or use:

readlink -f $(which java)

Import the Certificate

sudo keytool -import -alias customcert -keystore /path/to/cacerts -file customcert.pem

Confirm trust and enter the password (changeit).


🐳 Adding Certificate to OpenLegacy Docker Image

To integrate certificates into Docker containers like openlegacy/hub-enterprise:latest, follow these steps:

Extend the Docker Image

Create a Dockerfile:

FROM openlegacy/hub-enterprise:latest

COPY customcert.pem /tmp/customcert.pem

RUN keytool -import -alias customcert -keystore $JAVA_HOME/lib/security/cacerts \
    -file /tmp/customcert.pem -storepass changeit -noprompt

RUN rm /tmp/customcert.pem

Then build your image:

docker build -t openlegacy/hub-enterprise:latest-custom-ca .

Use this image instead of the default when starting your container.


🕵️ Final Tips

  • Always back up your original cacerts before modifying it.
  • For production, consider using a Certificate Authority or internal CA with root cert added organization-wide.