Wie sollte ich das tun hostname-Validierung bei der Verwendung von JSSE?

Schreibe ich einen client in Java (arbeiten muss sowohl auf dem desktop als JRE und Android) für ein proprietäres Protokoll (spezifisch für meine Firma) übernommen, TLS. Ich versuche herauszufinden, der beste Weg zu schreiben, eine TLS-client in Java, und insbesondere, stellen Sie sicher, dass es nicht hostname-Validierung richtig. (Edit: Von denen, ich meine die Prüfung, dass der hostname entspricht dem X. 509-Zertifikat, um zu vermeiden, man-in-the-middle-Angriffe.)

JSSE ist die offensichtliche API für das schreiben eines TLS-client, aber ich bemerkte aus den "Die meisten Gefährlichen Code in die Welt" Papier (wie auch aus Experimenten), dass JSSE nicht bestätigen hostname wenn man mit der SSLSocketFactory-API. (Das ist, was ich verwenden, da mein Protokoll nicht HTTPS.)

So, es scheint, dass bei der Verwendung von JSSE, ich habe zu tun hostname Validierung mich. Und anstatt zu schreiben, dass der code von Grund auf neu (ich würde mich da fast sicher falsch), es scheint, dass ich "borgen" einige der bestehenden code, der funktioniert. So, der wahrscheinlichste Kandidat, die ich gefunden habe, ist den Apache HttpComponents-Bibliothek (ironisch, da bin ich nicht tatsächlich zu tun HTTP) , und verwenden Sie die org.apache.http.conn.ssl.SSLSocketFactory-Klasse anstelle der standard javax.net.ssl.SSLSocketFactory-Klasse.

Meine Frage ist: ist das ein vernünftiges Vorgehen? Oder habe ich das völlig missverstanden Dinge, Weg aus dem tiefen Ende, und es ist eigentlich ein viel einfacher Weg, um hostname-Validierung in JSSE, ohne ziehen in einem Drittanbieter-Bibliothek wie HttpComponents?

Ich auch angeschaut, BouncyCastle, auch die hat eine nicht-JSSE-API für TLS, aber es scheint noch mehr beschränkt, als dass Sie nicht auch tun certificate chain validation, viel weniger hostname-Validierung, so schien es wie ein non-starter.

Edit: Diese Frage beantwortet wurde für Java 7, aber ich bin immer noch neugierig, was die "best practice" für Java 6 und Android. (Insbesondere habe ich Unterstützung von Android für meine Anwendung.)

Wieder bearbeitet: Zu machen, mein Vorschlag "ausleihen von Apache HttpComponents" zu konkretisieren, habe ich einen kleine Bibliothek enthält die HostnameVerifier-Implementierungen (vor allem StrictHostnameVerifier und BrowserCompatHostnameVerifier) extrahiert aus Apache HttpComponents. (Ich erkannte alles, was ich brauche, sind die Teilnehmerinnen und brauche ich nicht, der Apache ist SSLSocketFactory, wie ich ursprünglich zu denken.) Wenn Links auf meine eigenen Geräte, das ist die Lösung, die ich verwende. Aber Erstens, gibt es einen Grund, mich sollte nicht tun es auf diese Weise? (Unter der Annahme, dass mein Ziel ist, mein hostname-Validierung die gleichen wie https funktioniert. Ich merke, dass sich zur Diskussion, und diskutiert wurde in dem thread auf den Kryptographie-Liste, aber jetzt ich ' m kleben mit HTTPS-wie hostname-Validierung, auch wenn ich es nicht mache HTTPS.)

Vorausgesetzt, es ist nichts "falsch" meine Lösung, meine Frage ist: gibt es eine "bessere" Art und Weise, es zu tun, während immer noch tragbar in Java 6, Java 7 und Android? (Wobei "besser" bedeutet, dass mehr Redewendungen, die bereits weit verbreitet, und/oder benötigen weniger externe code.)

  • Ich kann nicht wirklich herausfinden, warum das so schwer downvoted und auf Eis gelegt, da off-topic. Wie die Umsetzung hostname-Validierung bei der Verwendung von JSSE ist ganz klar on-topic! (Die Frage auch klar zu erwähnen, welche APIs berücksichtigt wurden.)
  • Wo würde der richtige Ort, diese Frage zu stellen? Ich habe nicht in der Lage zu finden, eine mailing-Liste für JSSE. Gibt es eine?
  • Während der Wartezeit für diese Frage (hoffentlich) wieder eröffnet, die Sie interessieren könnten (das sollte Ihnen eine Antwort für Java 7): stackoverflow.com/a/17979954/372643
  • Danke @Bruno! Das ist eigentlich eine nützliche Antwort auf meine Frage. (Leider hatte ich nicht gefunden, dass der thread vorher bei der Suche nach Antworten.) Das heißt, ich kann wahrscheinlich nicht nutzen, da, obwohl ich kann in der Lage sein, um Weg mit zu sagen, wir haben mit Java 7 statt Java 6 auf dem desktop, das problem ist, dass ich auch Unterstützung von Android, und ich bin Wetten, dass Android bietet keine Unterstützung für die neuen Java 7, was, da es nicht wirklich Java-kompatible jedenfalls. Aber jetzt vielleicht die Antwort ist, dass ich gehen sollte, daß diese Frage in einem Android-forum.
  • Diese Frage ist nicht off-topic an alle. Dies ist eine wichtige Frage, die schlecht behandelt, die in der Dokumentation. Während die Frage bezieht sich auf einen code, die Frage ist nicht, über seine Umsetzung: es geht darum, wie lösen ein Allgemeines problem konfrontiert, durch Dritte unter Verwendung der Java-Implementierung von SSL.
  • Wenn es ein proprietäres Protokoll ist, und Sie nur eine Verbindung zu Ihrem eigenen Server, können Sie überprüfen, cert, wie Sie wollen, aber es wäre im Allgemeinen: ist es von einer vertrauenswürdigen ZERTIFIZIERUNGSSTELLE ausgestellte oder verkettet zu einer vertrauenswürdigen Wurzel; und Sie tut das Zertifikat Namen der server, die Sie glauben, dass Sie sich verbinden (möglicherweise durch einen DNS-Namen, kann aber kein proprietäres Namensschema). Für ein solches Protokoll HTTPS-style-name matching (mit wildcards, etc.) ist wahrscheinlich übertrieben.
  • Ich denke, im Grunde muss man das, was angedeutet wird durch die javax.net.ssl.HostnameVerifier-Schnittstelle. Zumindest dies würde Ihnen eine JDK-konforme Art und Weise der Verpackung, was die Umsetzung, Sie kommen mit. Ich Stimme vollkommen mit @Bruno und andere, die diese Frage zu 100% on-topic und ich gestimmt habe, zu öffnen. Sie nicht brauchen, Tim Dierk ersten zwei Punkte, da JSSE bereits überprüft, die, Sie benötigen jedoch die Dritte. Wo genau in der Bescheinigung der hostname sein soll und wie es passen kann variieren, aber im Allgemeinen, die Sie tun können, noch schlimmer als die Folgen der HTTPS-Spezifikation für dieses bit.
  • Ich Plane auf tun, https-Stil Validierung, obwohl ich bin mir noch nicht sicher, ob ich brauche wildcards oder nicht. Ja, HostnameVerifier ziemlich viel tut, was ich will, aber es scheint, dass die JDK-nur hat die HostnameVerifier-Schnittstelle, und nicht öffentlich bieten konkrete Implementierungen von HostnameVerifier. Das ist, warum ich immer noch meine Augen auf Apache HttpComponents; es stellt konkrete Implementierungen wie StrictHostnameVerifier und BrowserCompatHostnameVerifier. Obwohl die einen leichten Nachteil HostnameVerifier ist, dass es nur gibt true oder false zurück, anstatt eine Fehlermeldung, wenn es fehlschlägt.
  • Das JDK hat eine HostNameVerifier gebaut, natürlich, und Sie können es mit HttpsURLConnection.getDefaultHostnameVerifier(). Aber mein Punkt war eigentlich, dass diese Schnittstelle gibt genug die API, die Sie brauchen, um zu implementieren: d.h. alles, was Sie brauchen Zugriff auf den Hostnamen, und die SSLSession. Aber wenn Sie mehr als einen boolean-ich denke, das wird nicht funktionieren.
  • Für die weitere Diskussion um dieses, ich ' ll zeigen Sie auf diese mailing-Liste-thread: lists.randombit.net/pipermail/cryptography/2013-August/... : "best practices" für die hostname-Validierung bei der Verwendung von JSSE
  • Suche an der Quelle für OpenJDK 6, HttpsURLConnection.getDefaultHostnameVerifier() gibt eine Instanz der Sonne.net.www.Protokoll.https.DefaultHostnameVerifier, die eine stub-Klasse, deren verify () - Methode immer false zurück. Ich bin immer noch durch den code, und es ist schwer zu Folgen, aber es sieht (zumindest einige von) die Magie passiert in der checkURLSpoofing () - Methode der Sonne.net.www.Protokoll.http.HttpsClient, und tatsächlich wird die Klasse sun.Sicherheit.util.HostnameChecker (die nicht implementiert HostnameVerifier interface) zu überprüfen, X509-Zertifikat...
  • ...und er ruft nur die vom Benutzer angegebenen HostnameVerifier wenn HostnameChecker ausfällt. Es gibt auch einige böse Dinge in den afterConnect () - Methode, wo es überprüft, ob die HostnameVerifier ist ein instanceof-DefaultHostnameVerifier, und hat etwas besonderes in diesem Fall. Ich habe noch nicht herausgefunden, dass es alle schon, aber es scheint sehr hinterhältig. Auf der anderen Seite, Android (aka Harmonie) hat eine völlig andere (und einfachere) Architektur, wo getDefaultHostnameVerifier() eigentlich nicht geben Sie eine HostnameVerifier die das X509-Prüfung selbst.
  • In Bezug auf "hostname-Validierung die gleichen wie https funktioniert [...]": das ist, warum es ist RFC 6125, zu vereinheitlichen das Verhalten über Protokolle. Konkret, es ist sehr ähnlich zu dem, was HTTPS sagt sowieso (außer es funktioniert nicht mit IP-Adressen).

InformationsquelleAutor user2666524 | 2013-08-09
Schreibe einen Kommentar