Mon client SSL (Java) n'est pas l'envoi d'un certificat sur le serveur dans les deux sens de communication SSL
Dans une Java 1.7 application qui s'exécute sur Windows 7, je suis en train de faire 2-way SSL avec un serveur (un jeton de carte à puce est de fournir mon client certs via openSC). Le certificat du serveur est d'obtenir vérifié par le client, mais le client ne répond pas au serveur de la demande de certificat. Je crois que c'est parce que le client n'est pas en mesure de faire une chaîne de mon certificat à l'un de ceux demandés par le serveur (même si il existe une chaîne).
Voici le SSL de débogage du serveur de Demande de Certificat et les clients de réponse vide:
*** 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
***
Mon client cert est comme suit:
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]
Via clé-outil, j'ai également installé dans le truststore (java fichier cacerts), ce qui devrait être le lien entre mon cert de l'émetteur, DOD CA-30, et ce que le serveur demande, DoD Root CA 2.
De 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
La question est donc, pourquoi ne peut pas le client à faire la chaîne de certificats pour la réponse? Voici le code correspondant:
//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());
...
Et l'erreur que j'obtiens en retour, c'est que le serveur renvoie un 403. Probablement parce que le client n'envoie pas un client cert.
OriginalL'auteur PaulP | 2012-07-31
Vous devez vous connecter pour publier un commentaire.
Même si il semble que vous ne l'ai copié une partie du CA de la liste envoyée par le serveur sur cette question, je vais supposer que
CN=DOD CA-30, OU=PKI, OU=DoD, O=U.S. Government, C=US
n'est pas dans cette liste.Ce qui semble être manquant dans la chaîne de ce certificat (que vous mentionnez plus tard):
Importer des certificats dans votre client truststore a absolument aucun effet sur le certificat, le client envoie. Le client-certificat et sa clé privée) doit être mis en place dans le client keystore. En outre, si vous souhaitez envoyer un certificat client de la chaîne (qui sera ici nécessaire, si le serveur n'offre pas cet intermédiaire certificat d'autorité de certification dans sa liste), vous aurez besoin d'associer la totalité de la chaîne de certificat d'entrée. Ce n'est pas juste assez pour mettre les autres certificats dans le magasin de clés.
Pour résoudre ce problème, vous devez configurer votre fichier de stockage des clés d'entrée avec le client-la chaîne de certificats. Cela peut être effectué comme décrit dans cette réponse. Toutefois, il est possible que le fait que c'est un jeton matériel accessible via PKCS#11 pourrait les rendre un peu plus compliqué (peut-être il y a un autre certificat de gestion de l'outil fourni avec la carte, éventuellement indépendant de Java).
OriginalL'auteur Bruno
Depuis que je sais qui j'ai besoin de certificat à utiliser pour l'authentification du serveur, je peux forcer le client à envoyer ce certificat spécifique en étendant X509ExtendedKeyManager, et en remplaçant la chooseClientAlias() la méthode retourne toujours la alias de ce certificat. Code:
Donc, comme vous pouvez le voir, je le prends dans un defaultKeyManager qui reporter à rien, sauf ce que je veux remplacer. Ensuite, pour l'utiliser dans vos sslContext, procédez de la manière suivante:
Ce que vous pouvez faire est trop pour remplacer
getCertificateChain
pour ajouter ce certificat à la chaîne manuellement.Correct, c'est en supposant que le serveur a la pleine cert chaîne disponible.
OriginalL'auteur PaulP