Java HTTPS-Clientzertifikatauthentifizierung

222

Ich bin ziemlich neu in HTTPS/SSL/TLSund 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 POSTDaten für eine bestimmte Person ausführen muss URL. Dieser Teil funktioniert gut, das einzige Problem ist, dass er erledigt werden soll HTTPS. Der HTTPSTeil ist ziemlich einfach zu handhaben (entweder mit HTTPclientoder unter Verwendung der integrierten HTTPSUnterstü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 PCAPDumps ü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 JKSDatei 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/TLSdaher würde ich mich auch über Hintergrundinformationen freuen (muss kein Aufsatz sein; ich werde mich mit Links zu guten Artikeln zufrieden geben).

tmbrggmn
quelle
Ich habe zwei Zertifikate vom Client gegeben, um zu identifizieren, welche in Keystore und Truststore hinzugefügt werden müssen. Könnten Sie bitte helfen, dieses Problem zu identifizieren, da Sie bereits ein ähnliches Problem durchlaufen haben. Dieses Problem, das ich angesprochen
henrycharles

Antworten:

233

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

  1. Die Öffentlichkeit des Kunden Zertifikat des (in diesem Fall von einer selbstsignierten Zertifizierungsstelle signiert)
  2. Der private Schlüssel des Clients

Um es zu generieren, habe ich zum Beispiel den OpenSSL- pkcs12Befehl 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

  1. Die Clientzertifikatauthentifizierung kann nur vom Server erzwungen werden.
  2. ( 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.
  3. 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=sslist aber strukturierter und (wohl) einfacher zu interpretieren, wenn Sie mit der Java SSL-Debug-Ausgabe nicht vertraut sind.
  4. 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
tmbrggmn
quelle
6
"Wenn das Client-Zertifikat, das Sie zur Authentifizierung vorlegen möchten, nicht von einer dieser Zertifizierungsstellen signiert ist, wird es überhaupt nicht angezeigt." Die Zertifikate werden nicht angezeigt, da der Client weiß, dass sie vom Server nicht akzeptiert werden. Außerdem kann Ihr Zertifikat von einer Zwischenzertifizierungsstelle "ICA" signiert werden, und der Server kann Ihrem Client die Stammzertifizierungsstelle "RCA" präsentieren. In Ihrem Webbrowser können Sie Ihr Zertifikat weiterhin auswählen, obwohl es von ICA und nicht von RCA signiert ist.
KyleM
2
Stellen Sie sich als Beispiel für den obigen Kommentar eine Situation vor, in der Sie eine Stammzertifizierungsstelle (RCA1) und zwei Zwischenzertifizierungsstellen (ICA1 und ICA2) haben. Wenn Sie unter Apache Tomcat RCA1 in den Trust Store importieren, zeigt Ihr Webbrowser ALLE von ICA1 und ICA2 signierten Zertifikate an, auch wenn sie sich nicht in Ihrem Trust Store befinden. Dies liegt daran, dass es auf die Kette ankommt, nicht auf einzelne Zertifikate.
KyleM
2
"Meiner Meinung nach ist das ein seltsames Verhalten, aber ich bin sicher, es gibt einen Grund dafür." Der Grund dafür ist, dass dies in RFC 2246 steht. Nichts Seltsames daran. Es wäre seltsam, wenn Clients Zertifikate vorlegen dürfen, die vom Server nicht akzeptiert werden, und dies ist eine völlige Verschwendung von Zeit und Raum.
Marquis von Lorne
1
Ich würde dringend davon abraten, einen einzelnen JVM-weiten Keystore (und Truststore!) Zu verwenden, wie Sie es in Ihrem obigen Beispiel getan haben. Das Anpassen einer einzelnen Verbindung ist sicherer und flexibler, erfordert jedoch, dass Sie etwas mehr Code schreiben. Sie müssen das SSLContextwie in @ Magnus 'Antwort anpassen .
Christopher Schultz
63

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:

String keyPassphrase = "";

KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream("cert-key-pair.pfx"), keyPassphrase.toCharArray());

SSLContext sslContext = SSLContexts.custom()
        .loadKeyMaterial(keyStore, null)
        .build();

HttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build();
HttpResponse response = httpClient.execute(new HttpGet("https://example.com"));
Magnus
quelle
Ich musste benutzen sslContext = SSLContexts.custom().loadTrustMaterial(keyFile, PASSWORD).build();. Ich konnte es nicht zum Laufen bringen loadKeyMaterial(...).
Conor Svensson
4
@ ConorSvensson Vertrauensmaterial ist für den Client bestimmt, der dem Remoteserverzertifikat vertraut, Schlüsselmaterial ist für den Server, der dem Client vertraut.
Magnus
1
Ich mag diese prägnante und punktgenaue Antwort sehr. Bei Interesse stelle ich hier ein Beispiel mit Bauanweisungen zur Verfügung. stackoverflow.com/a/46821977/154527
Alain O'Dea
3
Du hast meinen Tag gerettet! Nur eine zusätzliche Änderung, die ich vornehmen musste, senden Sie das Passwort auch in loadKeyMaterial(keystore, keyPassphrase.toCharArray())Code '!
AnandShanbhag
1
@peterh Ja, es ist spezifisch für Apache http. Jede HTTP-Bibliothek hat ihre eigene Art der Konfiguration, aber die meisten von ihnen sollten irgendwie eine verwenden SSLContext.
Magnus
30

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 Client ‚s - Speicher wird die Kunden enthält privates und öffentliches Schlüsselpaar. Es wird als Keystore bezeichnet .
  • Der Speicher des Servers enthält den öffentlichen Schlüssel des Clients . Es wird als Truststore bezeichnet .

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:

-Djavax.net.ssl.keyStore=clientsidestore.jks

und auf dem Server:

-Djavax.net.ssl.trustStore=serversidestore.jks

Verwenden Sie zum Exportieren des Client-Zertifikats (öffentlicher Schlüssel) in eine Datei, damit Sie es auf den Server kopieren können

keytool -export -alias MYKEY -file publicclientkey.cer -store clientsidestore.jks

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).

keytool -import -file publicclientkey.cer -store serversidestore.jks
mhaller
quelle
Ich sollte wahrscheinlich erwähnen, dass ich keine Kontrolle über den Server habe. Der Server hat unser öffentliches Zertifikat importiert. Die Administratoren dieses Systems haben mir mitgeteilt, dass ich das Zertifikat explizit bereitstellen muss, damit es während des Handshakes gesendet werden kann (der Server fordert dies ausdrücklich an).
tmbrggmn
Sie benötigen öffentliche und private Schlüssel für Ihr öffentliches Zertifikat (das dem Server bekannte) als JKS-Datei.
sfussenegger
Danke für den Beispielcode. Was genau ist "mykey-public.cer" im obigen Code? Ist dies das öffentliche Client-Zertifikat (wir verwenden selbstsignierte Zertifikate)?
tmbrggmn
Ja, ich habe die Dateien in den Codefragmenten entsprechend umbenannt. Ich hoffe das macht es klar.
mhaller
Richtig, danke. Ich bin immer wieder verwirrt, weil anscheinend "Schlüssel" und "Zertifikat" synonym verwendet werden.
tmbrggmn
10

Maven pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>some.examples</groupId>
    <artifactId>sslcliauth</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>sslcliauth</name>
    <dependencies>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.4</version>
        </dependency>
    </dependencies>
</project>

Java-Code:

package some.examples;

import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.http.entity.InputStreamEntity;

public class SSLCliAuthExample {

private static final Logger LOG = Logger.getLogger(SSLCliAuthExample.class.getName());

private static final String CA_KEYSTORE_TYPE = KeyStore.getDefaultType(); //"JKS";
private static final String CA_KEYSTORE_PATH = "./cacert.jks";
private static final String CA_KEYSTORE_PASS = "changeit";

private static final String CLIENT_KEYSTORE_TYPE = "PKCS12";
private static final String CLIENT_KEYSTORE_PATH = "./client.p12";
private static final String CLIENT_KEYSTORE_PASS = "changeit";

public static void main(String[] args) throws Exception {
    requestTimestamp();
}

public final static void requestTimestamp() throws Exception {
    SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(
            createSslCustomContext(),
            new String[]{"TLSv1"}, // Allow TLSv1 protocol only
            null,
            SSLConnectionSocketFactory.getDefaultHostnameVerifier());
    try (CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(csf).build()) {
        HttpPost req = new HttpPost("https://changeit.com/changeit");
        req.setConfig(configureRequest());
        HttpEntity ent = new InputStreamEntity(new FileInputStream("./bytes.bin"));
        req.setEntity(ent);
        try (CloseableHttpResponse response = httpclient.execute(req)) {
            HttpEntity entity = response.getEntity();
            LOG.log(Level.INFO, "*** Reponse status: {0}", response.getStatusLine());
            EntityUtils.consume(entity);
            LOG.log(Level.INFO, "*** Response entity: {0}", entity.toString());
        }
    }
}

public static RequestConfig configureRequest() {
    HttpHost proxy = new HttpHost("changeit.local", 8080, "http");
    RequestConfig config = RequestConfig.custom()
            .setProxy(proxy)
            .build();
    return config;
}

public static SSLContext createSslCustomContext() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, KeyManagementException, UnrecoverableKeyException {
    // Trusted CA keystore
    KeyStore tks = KeyStore.getInstance(CA_KEYSTORE_TYPE);
    tks.load(new FileInputStream(CA_KEYSTORE_PATH), CA_KEYSTORE_PASS.toCharArray());

    // Client keystore
    KeyStore cks = KeyStore.getInstance(CLIENT_KEYSTORE_TYPE);
    cks.load(new FileInputStream(CLIENT_KEYSTORE_PATH), CLIENT_KEYSTORE_PASS.toCharArray());

    SSLContext sslcontext = SSLContexts.custom()
            //.loadTrustMaterial(tks, new TrustSelfSignedStrategy()) // use it to customize
            .loadKeyMaterial(cks, CLIENT_KEYSTORE_PASS.toCharArray()) // load client certificate
            .build();
    return sslcontext;
}

}
Kinjelom
quelle
Wenn Sie das Zertifikat lieber für alle Anwendungen verfügbar haben möchten, die eine bestimmte JVM-Installation verwenden, befolgen Sie stattdessen diese Antwort .
ADTC
Ist die Methode configureRequest()zum Festlegen des Proxys des Client-Projekts richtig?
Shareef
Ja, es ist eine http-Client-Konfiguration und in diesem Fall eine Proxy-Konfiguration
kinjelom
Vielleicht habe ich eine dumme Frage, aber wie erstelle ich eine Datei cacert.jks? Ich habe eine Ausnahme Ausnahme im Thread "main" java.io.FileNotFoundException :. \ Cacert.jks (Das System kann die angegebene Datei nicht finden)
Patlatus
6

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.

Hans
quelle
1
Denken Sie, Sie haben Tippfehler im Server CSR-Generierungsschritt: sollte server.keynicht verwendenclient.key
the.Legend
0

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):

  1. Sertifikatanforderung generieren:

    • Privaten Schlüssel generieren:

      openssl genrsa -des3 -passout pass:MY_PASSWORD -out user.key 2048
    • Zertifikatanforderung generieren:

      openssl req -new -key user.key -out user.csr -passin pass:MY_PASSWORD

    Behalten Sie user.key(und das Passwort) und senden Sie die Zertifikatsanfrage user.csran die Bank für mein Zertifikat

  2. Erhalten Sie 2 Zertifikate: mein Client-Stammzertifikat clientId.crtund Bank-Stammzertifikat:bank.crt

  3. Erstellen Sie einen Java-Keystore (geben Sie das Schlüsselkennwort ein und legen Sie das Keystore-Kennwort fest):

    openssl pkcs12 -export -in clientId.crt -inkey user.key -out keystore.p12 -name clientId -CAfile ca.crt -caname root

    Achten Sie nicht auf die Ausgabe : unable to write 'random state'. Java PKCS12 keystore.p12erstellt.

  4. bank.crtZum Keystore hinzufügen (der Einfachheit halber habe ich einen Keystore verwendet):

    keytool -import -alias banktestca -file banktestca.crt -keystore keystore.p12 -storepass javaops

    Überprüfen Sie die Keystore-Zertifikate wie folgt:

    keytool -list -keystore keystore.p12
  5. Bereit für Java-Code :) Ich habe Spring Boot RestTemplatemit Add- org.apache.httpcomponents.httpcoreAbhängigkeit verwendet:

    @Bean("sslRestTemplate")
    public RestTemplate sslRestTemplate() throws Exception {
      char[] storePassword = appProperties.getSslStorePassword().toCharArray();
      URL keyStore = new URL(appProperties.getSslStore());
    
      SSLContext sslContext = new SSLContextBuilder()
            .loadTrustMaterial(keyStore, storePassword)
      // use storePassword twice (with key password do not work)!!
            .loadKeyMaterial(keyStore, storePassword, storePassword) 
            .build();
    
      // Solve "Certificate doesn't match any of the subject alternative names"
      SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
    
      CloseableHttpClient client = HttpClients.custom().setSSLSocketFactory(socketFactory).build();
      HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(client);
      RestTemplate restTemplate = new RestTemplate(factory);
      // restTemplate.setMessageConverters(List.of(new Jaxb2RootElementHttpMessageConverter()));
      return restTemplate;
    }
Grigory Kislin
quelle
Sie können alles mit dem Keytool machen. OpenSSL ist hier überhaupt nicht erforderlich.
Marquis von Lorne
0

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:

    KeyStore keyStore = KeyStore.getInstance("pkcs12");
    keyStore.load(new FileInputStream(keyStorePath), keystorePassword.toCharArray());
    KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    kmf.init(keyStore, keystorePassword.toCharArray());
    SSLContext ctx = SSLContext.getInstance("TLS");
    ctx.init(kmf.getKeyManagers(), null, null);
    SSLSocketFactory sslSocketFactory = ctx.getSocketFactory();

    HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
    connection.setSSLSocketFactory(sslSocketFactory);

Die SSLContextInitialisierung dauert einige Zeit, daher möchten Sie sie möglicherweise zwischenspeichern.

Johannes Brodwall
quelle
-1

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.

Obi Wan Kenobi
quelle
1
Das PKCS12-Format wurde traditionell für privatekey-AND-cert verwendet, aber Java unterstützt seit 8 im Jahr 2014 (mehr als ein Jahr vor dieser Antwort) PKCS12, das cert (s) ohne privatekey (s) enthält. Unabhängig vom Keystore-Format erfordert die Clientauthentifizierung ein privates Schlüssel-UND-Zertifikat. Ich verstehe Ihren zweiten Satz nicht, aber der Java-Client kann automatisch ein Client-Zertifikat und einen Client-Schlüssel auswählen, wenn mindestens ein geeigneter Eintrag verfügbar ist, oder ein Keymanager kann so konfiguriert werden, dass er einen bestimmten verwendet.
dave_thompson_085
Ihr zweiter Satz ist völlig falsch. Der Server stellt seine vertrauenswürdigen Unterzeichner zur Verfügung, und der Client stirbt entweder oder stellt kein Zertifikat bereit, das diese Einschränkung erfüllt. Automatisch, nicht über 'in Ihrem Code'. Das ist der Server ‚Möglichkeit zu wissen , es repräsentiert einen Client‘.
Marquis von Lorne