web-dev-qa-db-fra.com

pourquoi Java n'envoie-t-il pas le certificat du client lors de l'établissement de la liaison SSL?)

J'essaie de me connecter à un service Web sécurisé.

J'avais un échec de négociation même si mon magasin de clés et mon magasin de clés de confiance ont été définis correctement.

Après plusieurs jours de frustration, de recherches sans fin sur Google et d'interroger tout le monde, j'ai découvert que le seul problème était que Java a choisi de ne pas envoyer le certificat client au serveur pendant la prise de contact.

Plus précisément:

  1. Le serveur a demandé un certificat client (CN = RootCA) - c'est-à-dire "donnez-moi un certificat qui est signé par l'autorité de certification racine"
  2. Java a examiné le magasin de clés et n'a trouvé que mon certificat client qui est signé par le "SubCA", lequel est à son tour émis par le "RootCA". Cela n'a pas pris la peine de regarder dans le magasin de confiance ... duh OK, je suppose
  3. Malheureusement, lorsque j'ai essayé d'ajouter le certificat "SubCA" au magasin de clés, cela n'a pas aidé du tout. J'ai vérifié si les certificats sont chargés dans le magasin de clés. Ils le font, mais KeyManager ignore tous les certificats sauf celui du client.
  4. Tout ce qui précède conduit au fait que Java) ne possède aucun certificat répondant à la demande du serveur et n'envoie rien ... échec de la négociation: tadaaa :-(

Mes questions:

  1. Est-il possible que j'ai ajouté le certificat "SubCA" au magasin de clés de manière à "rompre la chaîne de certificats" ou quelque chose de sorte que KeyManager charge uniquement le certificat client et ignore le reste? (Chrome et openssl parviennent à comprendre cela alors pourquoi ne pas utiliser Java? - notez que le certificat "SubCA" est toujours présenté séparément en tant qu'autorité de confiance, de sorte que Chrome le compresse apparemment correctement avec le cert client pendant la poignée de main)
  2. S'agit-il d'un "problème de configuration" formel côté serveur? Le serveur est un tiers. Je m'attendrais à ce que le serveur demande un certificat signé par l'autorité "SubCA", car c'est ce qu'il nous a fourni. Je soupçonne que le fait que cela fonctionne dans Chrome et openssl est dû au fait qu'ils sont "moins restrictifs" et Java va juste "à la livre" et échoue.

J'ai réussi à mettre en place une solution de contournement pour ce problème, mais je n'en suis pas très heureux, alors je serai heureux si quelqu'un peut clarifier celui-ci pour moi.

61
Jakub Hlavatý

Il est possible que vous ayez importé le certificat de l'autorité de certification intermédiaire dans le magasin de clés sans l'associer à l'entrée contenant votre certificat client et sa clé privée. Vous devriez pouvoir voir ceci en utilisant keytool -v -list -keystore store.jks. Si vous n'obtenez qu'un seul certificat par entrée d'alias, ils ne sont pas ensemble.

Vous devez importer votre certificat et sa chaîne ensemble dans l'alias du magasin de clés contenant votre clé privée.

Pour savoir quel alias de magasin de clés contient la clé privée, utilisez keytool -list -keystore store.jks (J'assume le type de magasin JKS ici). Cela vous dira quelque chose comme ça:

Your keystore contains 1 entry

myalias, Feb 15, 2012, PrivateKeyEntry, 
Certificate fingerprint (MD5): xxxxxxxx

Ici, l'alias est myalias. Si tu utilises -v en plus de cela, vous devriez voir Alias Name: myalias.

Si vous ne l'avez pas déjà séparément, exportez votre certificat client à partir du magasin de clés:

keytool -exportcert -rfc -file clientcert.pem -keystore store.jks -alias myalias

Cela devrait vous donner un fichier PEM.

En utilisant un éditeur de texte (ou cat), préparez le fichier (appelons-le bundle.pem) avec ce certificat client et le certificat d'autorité de certification intermédiaire (et éventuellement le certificat d'autorité de certification racine lui-même si vous le souhaitez), afin que le certificat client soit au début et que son certificat d'émetteur soit juste en dessous.

Cela devrait ressembler à:

-----BEGIN CERTIFICATE-----
MIICajCCAdOgAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVSzEa
....
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIICkjCCAfugAwIBAgIJAKm5bDEMxZd7MA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNV
....
-----END CERTIFICATE-----

Maintenant, réimportez ce paquet dans l’alias où se trouve votre clé privée:

keytool -importcert -keystore store.jks -alias myalias -file bundle.pem
91
Bruno

En tant qu’ajout ici, vous pouvez utiliser %> openssl s_client -connect Host.example.com:443 et voir la sauvegarde et vérifier que tous les principaux est valable contre le client. Vous recherchez ceci au bas de la sortie. Vérifiez le code retour: 0 (ok)

Si vous ajoutez - showcerts , toutes les informations relatives au trousseau seront envoyées avec le certificat d'hôte, ce que vous avez chargé dans votre trousseau.

5
tls