Helped a collegue yesterday for a few hours configuring his system with TLS certificates and showed code to enable authentication using client certificates. All easy enough if you know how… 🙂 Start by creating keys and certificates for a server and a person and create a Domino KYR keystore using the kyrtool from IBM. The below commands were all executed on Linux.
# change dir cd /local/notesdata/ # generate key and self-signed cert for server openssl genrsa -out server.key 4096 cat server.key openssl req -new -sha256 -key server.key -out server.csr openssl x509 -req -days 3650 -sha256 -in server.csr -signkey server.key -out server.pem # use kyrtool to generate kyr-file for Domino (all calls to startup below is actually # /opt/ibm/domino/bin/tools/startup startup /opt/ibm/domino/bin/kyrtool =/local/notesdata/notes.ini startup /opt/ibm/domino/bin/kyrtool =/local/notesdata/notes.ini create -k ./server.kyr -p password cat server.key > server.txt cat server.pem >> server.txt cat server.txt startup /opt/ibm/domino/bin/kyrtool =/local/notesdata/notes.ini verify ./server.txt startup /opt/ibm/domino/bin/kyrtool =/local/notesdata/notes.ini import all -k ./server.kyr -i ./server.txt startup /opt/ibm/domino/bin/kyrtool =/local/notesdata/notes.ini show keys -k ./server.kyr startup /opt/ibm/domino/bin/kyrtool =/local/notesdata/notes.ini show certs -k ./server.kyr # generate PKCS#12 for a user openssl genrsa -out person.key 4096 openssl req -new -sha256 -key person.key -out person.csr openssl x509 -req -days 3650 -sha256 -in person.csr -CA server.pem -CAkey server.key -out person.pem -CAcreateserial openssl x509 -in person.pem -text -noout openssl pkcs12 -export -out person.p12 -inkey person.key -in person.pem -certfile server.pem
Import the the person.p12 file on a person document in Domino Directory. Now copy server.kyr and server.sth to the Domino data dirctory and create an Internet Sites document using the keystore. Also edit the Internet Site document to allow certificate based authentication. The code below uses the PKCS#12 file to do an authenticated request using certificates as authentication.
package demo.intravision.certauth; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.security.KeyStore; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; public class Main { public static void main(String[] args) { try { new Main().run(); } catch (Throwable t) { t.printStackTrace(); } } public void run() throws Exception { // get url and open connection URL url = new URL("https://secure.krynn.local/testauth.nsf/username.json?open&login"); HttpURLConnection con = (HttpURLConnection)url.openConnection(); // apply SSL context (sets up the certificate to use for authentication etc) this.applySSLContext(con); // read from url BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8")); StringBuilder b = new StringBuilder(); String line = null; while (null != (line = reader.readLine())) { b.append(line).append('n'); } // show data System.out.println(b.toString()); // disconnect con.disconnect(); } private void applySSLContext(HttpURLConnection con) throws Exception { // password final char[] password = "password".toCharArray(); // input stream to pkcs12 file InputStream certificateInputStream = new FileInputStream("/Users/lekkim/Downloads/aran.p12"); // load key and key manager KeyStore ks = KeyStore.getInstance("PKCS12"); ks.load(certificateInputStream, password); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ks, password); // get trust manager X509TrustManager customTrustMgr = this.getTrustManager(); // build ssl context SSLContext sc = SSLContext.getInstance("TLSv1.2"); sc.init(kmf.getKeyManagers(), null == customTrustMgr ? null : new TrustManager[]{customTrustMgr}, null); // set socket facory if https if (con instanceof HttpsURLConnection) { HttpsURLConnection httpsCon = (HttpsURLConnection)con; httpsCon.setSSLSocketFactory(sc.getSocketFactory()); } } private X509TrustManager getTrustManager() throws Exception { // returning null uses the trust from the JVM cacerts keystore if ("1".equals("2")) return null; // define trust manager X509TrustManager customTrustMgr = new X509TrustManager() { @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[]{}; } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } }; return customTrustMgr; } }