Comment dois-je faire validation de nom de domaine lors de l'utilisation de JSSE?

Je suis en train d'écrire un client en Java (besoin de travailler à la fois sur le bureau JRE et sur Android) pour un protocole propriétaire (spécifique à mon entreprise) réalisée sur TLS. Je suis à essayer de comprendre la meilleure façon de rédiger un client TLS en Java, et en particulier, assurez-vous qu'il n'validation de nom de domaine correctement. (Edit: Par qui, je veux dire la vérification que le nom d'hôte correspond à l'X. 509 certificate, pour éviter man-in-the-middle attaques.)

JSSE est l'évidence de l'API pour la rédaction d'un client TLS, mais j'ai remarqué de la "La plupart de Code Dangereux dans le Monde" papier (ainsi que de l'expérimentation) que JSSE ne valide pas le nom de l'hôte lorsque l'on est à l'aide de la SSLSocketFactory API. (Qui est ce que j'ai à utiliser, car mon protocole n'est pas en HTTPS.)

Ainsi, il apparaît que lors de l'utilisation de JSSE, j'ai à faire, validation de nom de domaine me. Et, plutôt que d'écrire le code à partir de zéro (puisque j'aurais presque certainement se tromper), il semble que je doit "emprunter" le code existant qui fonctionne. Ainsi, le candidat le plus probable que j'ai trouvé est d'utiliser Apache HttpComponents bibliothèque (ironique, puisque je ne suis pas en train de faire HTTP) et l'utilisation de l'org.apache.http.conn.le protocole ssl.SSLSocketFactory classe en lieu et place de la norme javax.net.le protocole ssl.SSLSocketFactory classe.

Ma question est: est-ce raisonnable de cours de l'action? Ou ai-je complètement mal compris les choses, disparu à la fin de profondeur, et il y a effectivement un moyen beaucoup plus facile d'obtenir la validation de nom de domaine en JSSE, sans tirer dans une bibliothèque tierce, comme HttpComponents?

J'ai aussi regardé BouncyCastle, trop, ce qui est un non-JSSE API pour TLS, mais il semble être encore plus limité, en ce qu'il n'a même pas de faire un certificat de la chaîne de validation, beaucoup moins de validation de nom de domaine, de sorte qu'il semblait être un non-starter.

Edit: Cette question a été répondu pour Java 7, mais je suis toujours curieux de savoir ce que les "meilleures pratiques" pour la version 6 de Java et Android. (J'ai en particulier à l'appui de Android pour mon application.)

Réédité: Pour faire ma proposition de "emprunter de Apache HttpComponents" plus concrète, j'ai créé un petite bibliothèque qui contient le HostnameVerifier implémentations (notamment StrictHostnameVerifier et BrowserCompatHostnameVerifier) extrait de Apache HttpComponents. (J'ai réalisé tout ce que je besoin sont les vérificateurs, et je n'ai pas besoin d'Apache SSLSocketFactory comme je l'ai été à l'origine de la pensée.) Si la gauche pour moi, c'est la solution que je vais utiliser. Mais tout d'abord, est-il une raison je ne devrait pas faire de cette façon? (En supposant que mon objectif est de faire de mon nom d'hôte de la validation de la même façon https n'. Je me rends compte que lui-même est ouvert au débat, et qui a été discuté dans le fil sur la cryptographie liste, mais pour l'instant je suis coller avec HTTPS-comme la validation de nom de domaine, même si je ne le fais pas HTTPS.)

En supposant que il n'y a rien de "mal" avec ma solution, ma question est la suivante: est-il une "meilleure" façon de le faire, tout en restant portable à travers la version 6 de Java, Java 7, et Android? (Où "plus" signifie plus idiomatiques, déjà largement en cours d'utilisation, et/ou ayant besoin de moins de code externe.)

  • Je ne peux pas vraiment comprendre pourquoi cela a été si souvent downvoted et mis en attente comme hors-sujet. Comment mettre en œuvre validation de nom de domaine lors de l'utilisation de JSSE est clairement sur le sujet! (La question aussi clairement mention Api ont été pris en compte.)
  • aurait être le bon endroit pour poser cette question? Je n'ai pas été en mesure de trouver une liste de diffusion pour JSSE. Est-il un?
  • En attendant, pour cette question, pour être (espérons-le), a de nouveau ouvert, vous pourriez être intéressé par ce qui devrait vous donner une réponse pour Java 7): stackoverflow.com/a/17979954/372643
  • Merci @Bruno! C'est en fait une réponse utile à ma question. (Malheureusement, je n'avais pas trouvé ce thread avant lors de la recherche de réponses.) Cela dit, j'ai probablement ne peut pas l'utiliser car bien que j'ai pourrait être en mesure de s'en tirer en disant que nous devons utiliser Java 7 au lieu de Java 6 sur le bureau, le problème est que j'ai aussi besoin de soutien Android, et je parie que Android ne prend pas en charge le nouveau Java 7 chose, car il n'est pas vraiment Java compatible de toute façon. Mais maintenant, peut-être que la réponse est que je devrais aller poser cette question par Android-forum spécifique.
  • Cette question n'est pas hors-sujet du tout. C'est une question importante qui est mal abordé dans la documentation. Alors que la question fait référence à son code, la question n'est pas à propos de sa mise en œuvre: c'est sur la façon de résoudre un problème général rencontrées par la personne qui utilise le Java SSL mise en œuvre.
  • Si c'est un protocole propriétaire, et vous ne vous connectez vos propres serveurs, vous pouvez valider le cert de la manière que vous voulez, mais il comprend généralement: est-il émis par une autorité de certification de confiance, ou d'une chaîne à une racine de confiance; et le nom de certificat du serveur, vous croyez que vous êtes connecté à (peut-être par un nom DNS, mais pourrait être n'importe quel propriétaire de nommage). Pour un tel protocole HTTPS style de correspondance de nom (avec des caractères génériques, etc.) est probablement excessif.
  • Je pense que vous avez essentiellement besoin de ce qui est impliqué par la javax.net.le protocole ssl.HostnameVerifier interface. Au moins ce serait vous donner un JDK-conformité de l'emballage quel que soit mise en œuvre que vous venez avec. Je suis entièrement d'accord avec @Bruno et d'autres personnes que cette question est de 100% sur le sujet et j'ai voté pour la réouverture. Vous n'avez pas besoin de Tim Dierk les deux premiers points, comme JSSE déjà de vérifier ceux-ci, mais vous avez besoin de la troisième. Où exactement dans le certificat, le nom d'hôte doit être et comment il peut correspondre peut varier, mais en général, vous pourriez faire pire que de suivre la HTTPS spécification de ce bit.
  • Je vais la faire https style de validation, même si je ne suis pas encore sûr si j'ai besoin de caractères génériques ou pas. Oui, HostnameVerifier assez bien fait ce que je veux, mais il semble que le JDK seulement le HostnameVerifier interface, et n'a pas publiquement fournir des implémentations de HostnameVerifier. C'est pourquoi j'ai toujours mon oeil sur Apache HttpComponents; il fournit des implémentations concrètes comme StrictHostnameVerifier et BrowserCompatHostnameVerifier. Bien qu'un léger inconvénient à HostnameVerifier c'est qu'il ne retourne true ou false, plutôt qu'un message d'erreur en cas d'échec.
  • Le JDK n'ont HostNameVerifier construit dans, bien sûr, et vous pouvez obtenir avec HttpsURLConnection.getDefaultHostnameVerifier(). Mais mon point est vraiment que cette interface indique suffisamment l'API que vous avez besoin pour mettre en œuvre: c'est à dire tout ce que vous devez accès, le nom d'hôte et le SSLSession. Mais si vous avez besoin de plus qu'un booléen je suppose que ça ne fonctionne pas, soit.
  • Pour plus de discussion autour de cela, je vais point à cette liste de diffusion thread: lists.randombit.net/pipermail/cryptography/2013-August/... : "meilleures pratiques" pour la validation de nom de domaine lors de l'utilisation de JSSE
  • en regardant la source pour OpenJDK 6, HttpsURLConnection.getDefaultHostnameVerifier() renvoie une instance de soleil.net.www.le protocole.https.DefaultHostnameVerifier, qui est un stub de classe dont le vérifier() la méthode renvoie toujours false. Je travaille toujours à travers le code, et c'est dur à suivre, mais il ressemble (au moins une partie de) la magie qui se passe dans le checkURLSpoofing() la méthode de soleil.net.www.le protocole.http.HttpsClient, et il utilise la classe soleil.de sécurité.util.HostnameChecker (ce qui ne veut pas mettre en œuvre la HostnameVerifier interface) pour vérifier le certificat X509...
  • ...et il ne l'invoque fourni par l'utilisateur HostnameVerifier si HostnameChecker échoue. Il y a aussi de mauvaises choses qui se passent dans le afterConnect() la méthode, où il vérifie si le HostnameVerifier est un instanceof DefaultHostnameVerifier, et fait quelque chose de spécial dans ce cas. Je n'ai pas compris tous les encore sorti, mais il semble très sournois. D'autre part, Android (aka Harmonie) est totalement différent (et plus simple) de l'architecture, où getDefaultHostnameVerifier() ne fait de vous donner un HostnameVerifier qui ne l'X509 la vérification elle-même.
  • Concernant le "nom d'hôte de la validation de la même façon https ne [...]": c'est pourquoi il est le RFC 6125, d'unifier le comportement à l'échelle des protocoles. Concrètement, c'est très similaire à ce que HTTPS dit de toute façon (sauf qu'il ne gère pas les adresses IP).

InformationsquelleAutor user2666524 | 2013-08-09