If you ever find yourself having to establish SSL connection with untrusted server (eg: because the server’s cert is not chained to 3rd party CA (internal / testing servers)), you’ll probably use -Djavax.net.ssl.trustStore and -Djavax.net.ssl.trustStorePassword.
While this method works great for jvm-wide configuration, it’s a bit tricky if you want to apply it to specific class / method only. Also if you ever had to dynamically update the trust certificate, it might be harder to get this method working
Trusting Certificate Using SSLContext
Supposed you have a X.509 SSL certificate in Base 64 encoded PEM format like below:
-----BEGIN CERTIFICATE-----
MIIDBzCCAe+gAwIBAgIJAI1DCiDwQMQ0MA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNV
BAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xNDA0MzAyMjU1NTZaFw0yNDA0MjcyMjU1
NTZaMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAOjZRpPtBBrOE32MV2X1HlTmLFE3977o4k97CYZetgxZ
guLy+dPBaJ6fA3pjhkqXbICtsaBewAjnlvUgUilc0quwklepw9Sd9L6M9NgyCFGf
G1AFA8wEJwmtxA7TnDNjuqATqbLUOe2douuQ9Krttd5zbGB2vDO1Chc4GYb1pUxV
wTAdk+bXrpoeP/82LEYjcYq2UTXs/cUnzDAOzOCXcCugx2Rh2EdS/S6oXgOYv/BD
q1jVj3AojcJuJixW/BGWwvw/hkBof0RzrnJNqHnO3PWfc0LhOeqKwOhMZ9dV2p0m
v5X221nrBMwOZRDJBWybE5YuWmAt6ci2BtHgn3l4ClcCAwEAAaNQME4wHQYDVR0O
BBYEFBFwLKrHXhSyapQbXp/2E/R1VT0XMB8GA1UdIwQYMBaAFBFwLKrHXhSyapQb
Xp/2E/R1VT0XMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAMRaPuv
lFTZpAn8lCqom0Af8+3OGEPUEYPOReE0xG7Ph+OSPhlI860C0QwiZn0PR3L+QK2F
d1g9GndfJATgyjqbhebKXO1b0OAQfGIPsEHsCtT+4myFNHnYmHKqnX1NrUXpjzcP
4uHpVU7Nomz+f4WjH+cACL4PrlldPtXXOsn7vFdZrYunitHTvslWe3RoQCkHRc93
3OKx4Xh2Vy1wCrfkZYd8Q1y55jysxwitYhQAYwv9GyL/pj5jzB5PxLAZbDRznK5E
CbqiKbfbcAEpbxceXG0YmVYY/kEzXKPxUw99GH/hkUTFhCT03unx7LWtYI5BG5o+
QCVuzU8kMeiOFkQ=
-----END CERTIFICATE-----
You can trust this by setting up a SSLContext:
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream certFile = new FileInputStream("mycert.crt");
Certificate ca = cf.generateCertificate(certFile); // this is java.security.cert.Certificate;
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
TrustManager trustManager = TrustManagerUtils.getDefaultTrustManager(keyStore);
SSLContext sslContext = SSLContextUtils.createSSLContext("TLS", null /*keyManager*/, trustManager);
Here the certificate above is placed on mycert.crt file on java work directory. On SSLContextUtils.createSSLContext the keyManager param is set to null because we don’t need present any private keys. The TrustManagerUtils and SSLContextUtils came from commons-net package so you’ll need to add that dependency to your pom.xml:
commons-net
commons-net
3.3
SSLContext has a getSocketFactory() method which you can use to setup a SSLSocket which will verify against mycert.crt
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
Socket socket = socketFactory.createSocket("dev.mycompany.com", 1234);
You can also pass SSLContext directly to some other libraries for it to trust your cert, below is ftps example using commons-net
FTPSCLient ftps = new FTPSClient(true, sslContext);