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
- Die Öffentlichkeit des Kunden Zertifikat des (in diesem Fall von einer selbstsignierten Zertifizierungsstelle signiert)
- Der private Schlüssel des Clients
Um es zu generieren, habe ich zum Beispiel den OpenSSL- pkcs12
Befehl verwendet.
openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12 -name "Whatever"
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.
keytool -genkey -dname "cn=CLIENT" -alias truststorekey -keyalg RSA -keystore ./client-truststore.jks -keypass whatever -storepass whatever
keytool -import -keystore ./client-truststore.jks -file myca.crt -alias myca
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
- Die Clientzertifikatauthentifizierung kann nur vom Server erzwungen werden.
- ( Wichtig! ) Wenn der Server ein Client-Zertifikat anfordert (als Teil des TLS-Handshakes), stellt er im Rahmen der Zertifikatanforderung auch eine Liste vertrauenswürdiger Zertifizierungsstellen bereit. Wenn das Client-Zertifikat, das Sie zur Authentifizierung vorlegen möchten, nicht ist von einer dieser signiert ist, wird es überhaupt nicht angezeigt (meiner Meinung nach ist dies ein seltsames Verhalten, aber ich bin sicher, dass es einen Grund dafür gibt). Dies war die Hauptursache für meine Probleme, da die andere Partei ihren Server nicht richtig konfiguriert hatte, um mein selbstsigniertes Client-Zertifikat zu akzeptieren, und wir davon ausgegangen sind, dass das Problem an meinem Ende lag, weil das Client-Zertifikat in der Anforderung nicht ordnungsgemäß bereitgestellt wurde.
- Holen Sie sich Wireshark. Es verfügt über eine hervorragende SSL / HTTPS-Paketanalyse und ist eine enorme Hilfe beim Debuggen und Auffinden des Problems. Es ähnelt,
-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). ::
-Djavax.net.debug=ssl
-Djavax.net.ssl.keyStoreType=pkcs12
-Djavax.net.ssl.keyStore=client.p12
-Djavax.net.ssl.keyStorePassword=whatever
-Djavax.net.ssl.trustStoreType=jks
-Djavax.net.ssl.trustStore=client-truststore.jks
-Djavax.net.ssl.trustStorePassword=whatever