The Build

14:10

Why I prefer Python to Java, in two code samples.

22 October 2014

Assignment: Load a remote URL via https, verifying the site certificate against a local root CA certificate.

Java, Android SDK:

// Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// From https://www.washington.edu/itconnect/security/ca/load-der.crt
InputStream caInput = new BufferedInputStream(new FileInputStream("load-der.crt"));
Certificate ca;
try {
    ca = cf.generateCertificate(caInput);
    System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
    caInput.close();
}

// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);

// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);

// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);

// Tell the URLConnection to use a SocketFactory from our SSLContext
URL url = new URL("https://certs.cac.washington.edu/CAtest/");
HttpsURLConnection urlConnection =
    (HttpsURLConnection)url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
InputStream in = urlConnection.getInputStream();
copyInputStreamToOutputStream(in, System.out);

Python:

import requests
x = requests.get('https://certs.cac.washington.edu/CAtest/', verify='load-der.crt')

JS at 18:08, 23 October 2014:

Perai – o código Java tá errado: não tem os imports, nem a declaração de classe, nem declaração de método.
São pelo menos mais umas 5 linhas ai.

JS at 18:10, 23 October 2014:

Wait – the Java code is incomplete: it lacks the imports, class and and method declarations. Add at least 5 more lines for the set. And before anyone say it is “trivial” – the Python code run as is. The Java code will require these other parts to compile.

jminuscula at 10:11, 25 November 2014:

that’s definitely not fair. Requests is a third party library, all you’d need to do is encapsulate the java code into a library and then make the import. I’m pretty sure there are libraries that already do that for you.

In my opinion you should update the Python example to show how one would get to do it with the standard library… it’s still way more beautiful than Java :)

Xof at 10:35, 25 November 2014:

requests exists; that theoretical Java library doesn’t. Wrapping up the example in a separate function still makes it your code to debug and maintain.

There’s a deeper question, which is that Java and Python have philosophies about API and library design that run much deeper than this one example; that’s a subject for a separate post.