Mein SSL-Client (Java) sendet im Zwei-Wege-SSL-Handshake kein Zertifikat an den Server zurück
In einer Java 1.7-App unter Windows 7 versuche ich, 2-Wege-SSL mit einem Server durchzuführen (ein Smartcard-Token stellt meine Client-Zertifikate über openSC bereit). Das Serverzertifikat wird vom Client überprüft, aber der Client antwortet nicht auf die Zertifikatanforderung des Servers. Ich glaube, es liegt daran, dass der Client nicht in der Lage ist, eine Kette von meinem Zertifikat zu einer der vom Server angeforderten zu erstellen (obwohl eine solche Kette existiert).
Hier ist der SSL-Debug der Zertifikatanforderung des Servers und die leere Antwort des Clients:
*** 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=U.S. Government, C=US>
...
*** ServerHelloDone
*** Certificate chain
***
Mein Client-Zertifikat lautet wie folgt:
found key for : Certificate for PIV Authentication
chain [0] = [
[
Version: V3
Subject: CN=<...>, OU=CONTRACTOR, OU=PKI, OU=DoD, O=U.S. 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=U.S. Government, C=US
SerialNumber: [ 05bf13]
Über das Schlüsseltool habe ich auch im Truststore (Java Cacerts-Datei) installiert, was die Verbindung zwischen dem Aussteller meines Zertifikats, DOD CA-30, und dem, was der Server anfordert, DoD Root CA 2, sein soll.
Vom SSL-Debug:
adding as trusted cert:
Subject: CN=DOD CA-30, OU=PKI, OU=DoD, O=U.S. Government, C=US
Issuer: CN=DoD Root CA 2, OU=PKI, OU=DoD, O=U.S. 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=U.S. Government, C=US
Issuer: CN=DoD Root CA 2, OU=PKI, OU=DoD, O=U.S. 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
Die Frage ist also, warum der Client die Zertifikatskette für die Antwort nicht erstellen kann. Hier ist der relevante 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());
...
Und der Fehler, den ich zurück bekomme, ist, dass der Server eine 403 zurückgibt. Höchstwahrscheinlich, weil der Client ihm kein Client-Zertifikat gesendet hat.