Writing SSL Checker Using Java

Does anyone know any good tutorials, sites and books on writing SSL validation in Java? I am trying to do what can be found here: http://www.sslshopper.com/ssl-checker.html . I am not trying to create a self-signed certificate or use a keystore. I want to be able to access any site, determine if a valid SSL certificate exists, determine if the host name in the certificate matches the specified name, and determine when that certificate expires. I came across this topic, but "How to create an SSL buyer using Java" did not bring me anything, and my other search queries gave me only links to how to create a self-signed certificate. Any help would be greatly appreciated.

+6
source share
2 answers

To obtain a server certificate in the first place, to perform a manual check, regardless of whether it is valid or not, the easiest way to connect is through SSLSocket after disabling certificate verification.

Create an SSLContext that allows anything:

 SSLContext sslContext = SSLContext.getInstance("TLS"); X509TrustManager passthroughTrustManager = new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public X509Certificate[] getAcceptedIssuers() { return null; } }; sslContext.init(null, new TrustManager[] { passthroughTrustManager }, null); 

(Lateral note: for people who are looking for a way to use test certificates domestically, I would recommend creating your own test CA instead of disabling checks, just in case these dummy checks are mistakenly left in the production code, and also because it makes tests more realistic.)

Create a socket, connect and start the handshake explicitly (since you are not really going to read its form):

 SSLSocketFactory ssf = sslContext.getSocketFactory(); SSLSocket socket = (SSLSocket) ssf.createSocket( "the.host.name", 443); socket.startHandshake(); 

Get a peer certificate chain. The first element is the actual server certificate.

 X509Certificate[] peerCertificates = (X509Certificate[]) socket .getSession().getPeerCertificates(); 

If you want to confirm that there are default trusted certificates (default trusted CA certificates), build the X509TrustManager based on the default values ​​(this is actually what passthroughTrustManager disabled):

 // By default on Oracle JRE, algorithm is PKIX TrustManagerFactory tmf = TrustManagerFactory .getInstance(TrustManagerFactory.getDefaultAlgorithm()); // 'null' will initialise the tmf with the default CA certs installed // with the JRE. tmf.init((KeyStore) null); X509TrustManager tm = (X509TrustManager) tmf.getTrustManagers()[0]; 

Now check if the certificate is valid over time, whether it is verified by a trusted anchor and whether it has the correct extensions in accordance with RFC 3280 .

 try { // Assuming RSA key here. tm.checkServerTrusted(peerCertificates, "RSA"); } catch (CertificateException e) { // Here you may check which subclass of CertificateException to know what the error is. } 

All of the above uses the JSSE API .

Alternatively, if you want to delve into the PKIX details, you can use the Java Certification Paths API (which is used by JSSE).

(If you want to use only valid certificates, just use SSLContext sslContext = SSLContext.getDefault() at the beginning, create a socket and make a handshake.)

To get the server certificate directly, you can use this:

 X509Certificate serverCert = peerCertificates[0]; 

X509Certificate has a number of methods regarding dates and various extensions. For instance:

 Date expirationDate = serverCert.getNotAfter(); 

Hostname validation should follow RFC 6125 (or at least RFC 2818 ). In short, check to see if the host name you are going to connect to is one of the Subject Alternative Names (SAN) DNS records. Otherwise, return by checking if the host name is in the CN RDN of your certificate (for this you need to split the object DN by RDN). You may also be interested in this discussion (in the specific case of using IP addresses) .

It all depends on how many "manual" checks you want to do. There are a number of read specifications (RFC 5280 / RFC 3280 and RFC 6125 / RFC 2818, at least), in addition to the API docs.

This Security.SE question should also be of interest:

+3
source

What you can do is implement your own validation, e.g. Apache HttpClient
You must initialize the SSL context and override TrustManagers to perform any validation.

Hostname validation can be performed automatically by the library.

eg. The following will configure SSL socket processing to throw an exception if the host name does not match the certificate information:

 SSLSocketFactory sf = new SSLSocketFactory( SSLContext.getInstance("TLS"), SSLSocketFactory.STRICT_HOSTNAME_VERIFIER); 
+1
source

Source: https://habr.com/ru/post/903982/


All Articles