In the Java 1.7 application running on Windows 7, I am trying to do two-way SSL with the server (the smart card token provides my client certificates through openSC). The server certificate is accurately verified by the client, but the client does not respond to the server certificate request. I believe, because the client cannot make the chain from my certificate to one of those requested by the server (although such a chain exists).
Here's the debugging of the SSL server certificate request and the empty client request:
*** CertificateRequest Cert Types: RSA, DSS, ECDSA Cert Authorities: <CN=c4isuite-SDNI-DC02-CA, DC=c4isuite, DC=local> <CN=DoD Root CA 2, OU=PKI, OU=DoD, O=US Government, C=US> ... *** ServerHelloDone *** Certificate chain ***
My client certificate is as follows:
found key for : Certificate for PIV Authentication chain [0] = [ [ Version: V3 Subject: CN=<...>, OU=CONTRACTOR, OU=PKI, OU=DoD, O=US Government, C=US Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5 Key: Sun RSA public key, 2048 bits Issuer: CN=DOD CA-30, OU=PKI, OU=DoD, O=US Government, C=US SerialNumber: [ 05bf13]
Through a key tool, I also installed in truststore (the java cacerts file) what should be the connection between my cert certificate, DOD CA-30 and what the server is requesting, DoD Root CA 2.
SSL debugging:
adding as trusted cert: Subject: CN=DOD CA-30, OU=PKI, OU=DoD, O=US Government, C=US Issuer: CN=DoD Root CA 2, OU=PKI, OU=DoD, O=US Government, C=US Algorithm: RSA; Serial number: 0x1b5 Valid from Thu Sep 08 10:59:24 CDT 2011 until Fri Sep 08 10:59:24 CDT 2017 adding as trusted cert: Subject: CN=DoD Root CA 2, OU=PKI, OU=DoD, O=US Government, C=US Issuer: CN=DoD Root CA 2, OU=PKI, OU=DoD, O=US Government, C=US Algorithm: RSA; Serial number: 0x5 Valid from Mon Dec 13 09:00:10 CST 2004 until Wed Dec 05 09:00:10 CST 2029
So, the question is why the client cannot make a certificate chain for the response? Here is the relevant code:
// Create the keyStore from the SmartCard certs Provider provider = new sun.security.pkcs11.SunPKCS11(configName); Security.addProvider(provider); keyStore = KeyStore.getInstance("PKCS11", "SunPKCS11-SCR3310test"); char[] pin = PIN.toCharArray(); keyStore.load(null, pin); // Init the trustmanager TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(trustStore); // Create the client key manager LOG.info("Installing keystore with pin"); KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509"); keyManagerFactory.init(clientKeyStore, clientKeyPassword.toCharArray()); sslContext.init(keyManagerFactory.getKeyManagers(), tmf.getTrustManagers(), null); // Init SSL context SSLSocketFactory socketFactory = sslContext.getSocketFactory(); URL url = new URL(urlString); URLConnection connection = url.openConnection(); if (connection instanceof HttpsURLConnection) { LOG.info("Connection is HTTPS"); ((HttpsURLConnection) connection).setSSLSocketFactory(socketFactory); } // Send the request. connection.connect(); InputStreamReader in = new InputStreamReader((InputStream) connection.getContent()); ...
And the error I am returning is that the server returns 403. Most likely because the client did not send it a client certificate.