package chatty.util; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.security.KeyStore; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.logging.Logger; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.TrustManagerFactory; /** * Based on http://stackoverflow.com/a/34111150/2375667 * * @author tduva */ public class SSLUtil { private static final Logger LOGGER = Logger.getLogger(SSLUtil.class.getName()); private static void addCert(KeyStore keyStore, String certFile) throws Exception { CertificateFactory cf = CertificateFactory.getInstance("X.509"); try (InputStream caInput = new BufferedInputStream( SSLUtil.class.getResourceAsStream(certFile))) { Certificate crt = cf.generateCertificate(caInput); System.out.println("Added Cert for " + ((X509Certificate) crt) .getSubjectDN()); keyStore.setCertificateEntry(certFile, crt); } } public static SSLContext getSSLContextWithLE() throws Exception { // Load existing certs KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); Path ksPath = Paths.get(System.getProperty("java.home"), "lib", "security", "cacerts"); keyStore.load(Files.newInputStream(ksPath), "changeit".toCharArray()); addCert(keyStore, "DSTRootCAX3.crt"); addCert(keyStore, "isrgrootx1.crt"); // if (false) { // enable to see // System.out.println("Truststore now trusting: "); // PKIXParameters params = new PKIXParameters(keyStore); // params.getTrustAnchors().stream() // .map(TrustAnchor::getTrustedCert) // .map(X509Certificate::getSubjectDN) // .forEach(System.out::println); // System.out.println(); // } TrustManagerFactory tmf = TrustManagerFactory .getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(keyStore); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, tmf.getTrustManagers(), null); return sslContext; } public static void addLetsEncrypt() { try { SSLContext.setDefault(getSSLContextWithLE()); } catch (Exception e) { LOGGER.warning("Failed adding cert: "+e); } } public static void main(String[] args) throws IOException { addLetsEncrypt(); // signed by default trusted CAs. testUrl(new URL("https://google.com")); testUrl(new URL("https://www.thawte.com")); // signed by letsencrypt testUrl(new URL("https://helloworld.letsencrypt.org")); // signed by LE's cross-sign CA testUrl(new URL("https://letsencrypt.org")); // expired testUrl(new URL("https://tv.eurosport.com/")); // self-signed testUrl(new URL("https://www.pcwebshop.co.uk/")); } static void testUrl(URL url) throws IOException { URLConnection connection = url.openConnection(); try { connection.connect(); System.out.println("Headers of " + url + " => " + connection.getHeaderFields()); } catch (SSLHandshakeException e) { System.out.println("Untrusted: " + url); } } }