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);