Ich bin ziemlich neu in HTTPS/SSL/TLS
und ich bin ein bisschen verwirrt darüber, was genau die Clients bei der Authentifizierung mit Zertifikaten präsentieren sollen.
Ich schreibe einen Java-Client, der einfache POST
Daten für eine bestimmte Person ausführen muss URL
. Dieser Teil funktioniert gut, das einzige Problem ist, dass er erledigt werden soll HTTPS
. Der HTTPS
Teil ist ziemlich einfach zu handhaben (entweder mit HTTPclient
oder unter Verwendung der integrierten HTTPS
Unterstützung von Java ), aber ich bleibe bei der Authentifizierung mit Client-Zertifikaten. Mir ist aufgefallen, dass es hier bereits eine sehr ähnliche Frage gibt, die ich mit meinem Code noch nicht ausprobiert habe (wird dies früh genug tun). Mein aktuelles Problem ist, dass der Java-Client - was auch immer ich tue - niemals das Zertifikat mitsendet (ich kann dies mit PCAP
Dumps überprüfen ).
Ich möchte wissen, was genau der Client dem Server bei der Authentifizierung mit Zertifikaten präsentieren soll (speziell für Java - wenn das überhaupt wichtig ist). Ist das eine JKS
Datei oder PKCS#12
? Was soll in ihnen sein? nur das Client-Zertifikat oder ein Schlüssel? Wenn ja, welcher Schlüssel? Die verschiedenen Arten von Dateien, Zertifikatstypen und dergleichen sind ziemlich verwirrend.
Wie ich bereits sagte, bin ich neu in diesem Bereich, HTTPS/SSL/TLS
daher würde ich mich auch über Hintergrundinformationen freuen (muss kein Aufsatz sein; ich werde mich mit Links zu guten Artikeln zufrieden geben).
quelle
Antworten:
Endlich ist es gelungen, alle Probleme zu lösen, also werde ich meine eigene Frage beantworten. Dies sind die Einstellungen / Dateien, mit denen ich meine speziellen Probleme gelöst habe.
Der Keystore des Clients ist eine Datei im PKCS # 12-Format
Um es zu generieren, habe ich zum Beispiel den OpenSSL-
pkcs12
Befehl verwendet.Tipp: Stellen Sie sicher, dass Sie die neueste OpenSSL erhalten, nicht Stellen Version 0.9.8h erhalten, da dies anscheinend unter einem Fehler leidet, der es Ihnen nicht ermöglicht, PKCS # 12-Dateien ordnungsgemäß zu generieren.
Diese PKCS # 12-Datei wird vom Java-Client verwendet, um das Client-Zertifikat dem Server vorzulegen, wenn der Server den Client ausdrücklich zur Authentifizierung aufgefordert hat. Siehe den Wikipedia-Artikel zu TLS eine Übersicht über die tatsächliche Funktionsweise des Protokolls für die Authentifizierung von Clientzertifikaten (hier wird auch erläutert, warum wir den privaten Schlüssel des Clients benötigen).
Die Trusts des Kunden ist ein straight forward JKS - Format - Datei , die enthalten root oder Zwischen CA - Zertifikate . Diese CA-Zertifikate bestimmen, mit welchen Endpunkten Sie kommunizieren dürfen. In diesem Fall kann Ihr Client eine Verbindung zu dem Server herstellen, auf dem ein Zertifikat vorliegt, das von einer der CAs des Truststores signiert wurde.
Zum Generieren können Sie beispielsweise das Standard-Java-Keytool verwenden.
Mit diesem Truststore versucht Ihr Client, einen vollständigen SSL-Handshake mit allen Servern durchzuführen, die ein von der Zertifizierungsstelle signiertes Zertifikat vorlegen
myca.crt
.Die obigen Dateien sind ausschließlich für den Kunden bestimmt. Wenn Sie auch einen Server einrichten möchten, benötigt der Server eigene Schlüssel- und Truststore-Dateien. Auf dieser Website finden Sie eine gute Anleitung zum Einrichten eines voll funktionsfähigen Beispiels für einen Java-Client und einen Server (mit Tomcat) .
Probleme / Bemerkungen / Tipps
-Djavax.net.debug=ssl
ist aber strukturierter und (wohl) einfacher zu interpretieren, wenn Sie mit der Java SSL-Debug-Ausgabe nicht vertraut sind.Es ist durchaus möglich, die Apache httpclient-Bibliothek zu verwenden. Wenn Sie httpclient verwenden möchten, ersetzen Sie einfach die Ziel-URL durch das HTTPS-Äquivalent und fügen Sie die folgenden JVM-Argumente hinzu (die für jeden anderen Client gleich sind, unabhängig von der Bibliothek, die Sie zum Senden / Empfangen von Daten über HTTP / HTTPS verwenden möchten). ::
quelle
SSLContext
wie in @ Magnus 'Antwort anpassen .Andere Antworten zeigen, wie Client-Zertifikate global konfiguriert werden. Wenn Sie jedoch den Clientschlüssel für eine bestimmte Verbindung programmgesteuert definieren möchten, anstatt ihn global für jede Anwendung zu definieren, die auf Ihrer JVM ausgeführt wird, können Sie Ihren eigenen SSLContext folgendermaßen konfigurieren:
quelle
sslContext = SSLContexts.custom().loadTrustMaterial(keyFile, PASSWORD).build();
. Ich konnte es nicht zum Laufen bringenloadKeyMaterial(...)
.loadKeyMaterial(keystore, keyPassphrase.toCharArray())
Code '!SSLContext
.Die JKS-Datei ist nur ein Container für Zertifikate und Schlüsselpaare. In einem clientseitigen Authentifizierungsszenario befinden sich die verschiedenen Teile der Schlüssel hier:
Die Trennung von Truststore und Keystore ist nicht obligatorisch, wird jedoch empfohlen. Sie können dieselbe physische Datei sein.
Verwenden Sie die folgenden Systemeigenschaften, um die Dateisystemspeicherorte der beiden Speicher festzulegen:
und auf dem Server:
Verwenden Sie zum Exportieren des Client-Zertifikats (öffentlicher Schlüssel) in eine Datei, damit Sie es auf den Server kopieren können
Verwenden Sie zum Importieren des öffentlichen Schlüssels des Clients in den Keystore des Servers (wie auf dem Poster erwähnt, wurde dies bereits von den Serveradministratoren durchgeführt).
quelle
Maven pom.xml:
Java-Code:
quelle
configureRequest()
zum Festlegen des Proxys des Client-Projekts richtig?Für diejenigen unter Ihnen, die einfach eine bidirektionale Authentifizierung (Server- und Client-Zertifikate) einrichten möchten, führt eine Kombination dieser beiden Links dorthin:
Zweiwege-Authentifizierungs-Setup:
https://linuxconfig.org/apache-web-server-ssl-authentication
Sie müssen die erwähnte openssl-Konfigurationsdatei nicht verwenden. benutz einfach
$ openssl genrsa -des3 -out ca.key 4096
$ openssl req -new -x509 -days 365 -key ca.key -out ca.crt
So generieren Sie Ihr eigenes CA-Zertifikat und generieren und signieren die Server- und Client-Schlüssel über:
$ openssl genrsa -des3 -out server.key 4096
$ openssl req -new -key server.key -out server.csr
$ openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 100 -out server.crt
und
$ openssl genrsa -des3 -out client.key 4096
$ openssl req -new -key client.key -out client.csr
$ openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 101 -out client.crt
Für den Rest folgen Sie den Schritten im Link. Das Verwalten der Zertifikate für Chrome funktioniert genauso wie im genannten Beispiel für Firefox.
Richten Sie den Server als Nächstes ein über:
https://www.digitalocean.com/community/tutorials/how-to-create-a-ssl-certificate-on-apache-for-ubuntu-14-04
Beachten Sie, dass Sie die Server .crt und .key bereits erstellt haben, damit Sie diesen Schritt nicht mehr ausführen müssen.
quelle
server.key
nicht verwendenclient.key
Ich habe mit Spring Boot über bidirektionales SSL (Client- und Serverzertifikat) eine Verbindung zur Bank hergestellt. Beschreibe hier alle meine Schritte und hoffe, dass es jemandem hilft (einfachste funktionierende Lösung, die ich gefunden habe):
Sertifikatanforderung generieren:
Privaten Schlüssel generieren:
Zertifikatanforderung generieren:
Behalten Sie
user.key
(und das Passwort) und senden Sie die Zertifikatsanfrageuser.csr
an die Bank für mein ZertifikatErhalten Sie 2 Zertifikate: mein Client-Stammzertifikat
clientId.crt
und Bank-Stammzertifikat:bank.crt
Erstellen Sie einen Java-Keystore (geben Sie das Schlüsselkennwort ein und legen Sie das Keystore-Kennwort fest):
Achten Sie nicht auf die Ausgabe :
unable to write 'random state'
. Java PKCS12keystore.p12
erstellt.bank.crt
Zum Keystore hinzufügen (der Einfachheit halber habe ich einen Keystore verwendet):Überprüfen Sie die Keystore-Zertifikate wie folgt:
Bereit für Java-Code :) Ich habe Spring Boot
RestTemplate
mit Add-org.apache.httpcomponents.httpcore
Abhängigkeit verwendet:quelle
Bei einer p12-Datei mit dem Zertifikat und dem privaten Schlüssel (z. B. generiert durch openssl) verwendet der folgende Code diese für eine bestimmte HttpsURLConnection:
Die
SSLContext
Initialisierung dauert einige Zeit, daher möchten Sie sie möglicherweise zwischenspeichern.quelle
Ich denke, das Update hier war der Keystore-Typ, pkcs12 (pfx) haben immer einen privaten Schlüssel und der JKS-Typ kann ohne privaten Schlüssel existieren. Sofern Sie in Ihrem Code nichts angeben oder ein Zertifikat über den Browser auswählen, kann der Server nicht erkennen, dass er einen Client am anderen Ende darstellt.
quelle