Say I have two Java apps that I wrote: Ping.jar and Pong.jar and they get deployed and ran on two separate servers (Ping.jar deploys to srv-01.myorg.com and Pong.jar deploys to srv-02.myorg.com), and these two apps need to communicate with each other (2-way) via SSL. Let’s also assume that each app has its own SSL Certificate.
- How do I, a Java programmer, code
PingandPongto verify each other’s SSL cert? Does each CA provide some kind of RESTful API that I can hit with, say,HttpClient? Does Java have its own certificate-verifying API? Are there open source third party JARs or services I can use?
I was surprised by how little turned up when I searched for this online.
If you’re connecting using the Java SE SSL/TLS classes (e.g.
SSLSocketorSSLEngine), you’re using the Java Secure Socket Extension (JSSE).It will verify the remote party’s certificate according to the
SSLContextthat was used to create thisSSLSocketorSSLEngine.This
SSLContextwill be initialised withTrustManagerthat dictate how trust should be established.Unless you need specific configuration, you can often rely on the default values: this will rely on the PKIX algorithm (RFC 3280) to verify the certificate against a set of trust anchors (in
cacertsby default).cacerts, shipped with the Oracle JRE is a JKS keystore to which you can add additional certificates. You can add certificates explicitly usingkeytoolfor example.You can also create an
X509TrustManagerbased on a custom keystore programmatically (as described in this answer) and use it in a specificSSLContextthat doesn’t affect the default one.In addition to this, if you’re using your own protocol, you’ll need to verify that the certificate you’ve obtained matches the host name you were looking for (see RFC 6125). Typically, you can look for the subject alternative name in the
X509Certificateyou get (get the first peer certificate in the chain from theSSLSession), failing that, look for theCNRDN in the Subject Distinguished Name.