ssl disable - Autenticazione del certificato client HTTPS Java




all accept (6)

Penso che la correzione qui fosse il tipo di keystore, pkcs12 (pfx) ha sempre la chiave privata e il tipo JKS può esistere senza chiave privata. A meno che non si specifichi nel codice o si selezioni un certificato attraverso il browser, il server non ha modo di sapere che rappresenta un client all'altro capo.

Sono abbastanza nuovo su HTTPS / SSL / TLS e sono un po 'confuso su cosa dovrebbero presentare i client durante l'autenticazione con i certificati.

Sto scrivendo un client Java che ha bisogno di fare un semplice POST di dati per un particolare URL. Quella parte funziona bene, l'unico problema è che dovrebbe essere fatto su HTTPS. La parte HTTPS è abbastanza facile da gestire (con HTTPclient o utilizzando il supporto HTTPS integrato di Java), ma sono bloccato sull'autenticazione con i certificati client. Ho notato che c'è già una domanda molto simile qui, che non ho ancora provato con il mio codice (lo farò presto). Il mio problema attuale è che, qualunque cosa faccia, il client Java non invia mai il certificato (posso verificarlo con i dump PCAP).

Vorrei sapere che cosa si suppone che il client debba presentare al server durante l'autenticazione con i certificati (in particolare per Java - se questo è importante)? Si tratta di un file JKS o PKCS # 12? Cosa dovrebbe essere in loro; solo il certificato del cliente o una chiave? Se sì, quale chiave? C'è un po 'di confusione su tutti i diversi tipi di file, tipi di certificati e così via.

Come ho detto prima, sono nuovo in HTTPS / SSL / TLS quindi apprezzerei anche alcune informazioni di base (non deve essere un tema, mi accontento di link a buoni articoli).


Alla fine sono riuscito a risolvere tutti i problemi, quindi risponderò alla mia domanda. Queste sono le impostazioni / i file che ho usato per risolvere i miei problemi particolari risolti;

Il keystore del client è un file in formato PKCS # 12 contenente

  1. Il certificato pubblico del cliente (in questa istanza firmato da una CA autofirmata)
  2. La chiave privata del cliente

Per generarlo ho usato il comando pkcs12 di OpenSSL, per esempio;

openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12 -name "Whatever"

Suggerimento: assicurati di avere l'ultimo OpenSSL, non la versione 0.9.8h perché sembra che risenta di un bug che non ti consente di generare correttamente i file PKCS # 12.

Questo file PKCS # 12 verrà utilizzato dal client Java per presentare il certificato client al server quando il server ha richiesto esplicitamente al client di autenticarsi. Consulta l' articolo di Wikipedia su TLS per una panoramica di come funziona effettivamente il protocollo per l'autenticazione del certificato client (spiega anche perché abbiamo bisogno della chiave privata del client qui).

Il truststore del client è un file di formato JKS diretto contenente i certificati CA principali o intermedi . Questi certificati CA determineranno quali endpoint saranno autorizzati a comunicare, in questo caso consentiranno al client di connettersi a qualsiasi server presenti un certificato che è stato firmato da una delle CA del truststore.

Per generarlo è possibile utilizzare lo standard keytool Java, ad esempio;

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

Utilizzando questo truststore, il client proverà a eseguire un handshake SSL completo con tutti i server che presentano un certificato firmato dalla CA identificato da myca.crt .

I file qui sopra sono esclusivamente per il cliente. Quando si desidera configurare anche un server, il server necessita dei propri file key e truststore. In questo sito Web è possibile trovare una guida dettagliata per la configurazione di un esempio pienamente funzionante sia per un client Java che per un server (utilizzando Tomcat).

Problemi / Osservazioni / Consigli

  1. L'autenticazione del certificato client può essere applicata solo dal server.
  2. ( Importante! ) Quando il server richiede un certificato client (come parte dell'handshake TLS), fornirà anche un elenco di CA affidabili come parte della richiesta di certificato. Quando il certificato cliente che si desidera presentare per l'autenticazione non è firmato da una di queste CA, non verrà presentato affatto (a mio avviso, si tratta di un comportamento strano, ma sono sicuro che c'è una ragione per questo). Questa era la causa principale dei miei problemi, in quanto l'altra parte non aveva configurato correttamente il proprio server per accettare il mio certificato client autofirmato e ritenevamo che il problema fosse alla mia fine per non aver fornito correttamente il certificato client nella richiesta.
  3. Ottieni Wireshark. Ha un'ottima analisi del pacchetto SSL / HTTPS e sarà un enorme aiuto per il debug e la ricerca del problema. È simile a -Djavax.net.debug=ssl ma è più strutturato e (discutibilmente) più semplice da interpretare se non ti senti a tuo agio con l'output di debug SSL Java.
  4. È perfettamente possibile utilizzare la libreria Apache httpclient. Se si desidera utilizzare httpclient, è sufficiente sostituire l'URL di destinazione con l'equivalente HTTPS e aggiungere i seguenti argomenti JVM (che sono gli stessi per qualsiasi altro client, indipendentemente dalla libreria che si desidera utilizzare per inviare / ricevere dati tramite HTTP / HTTPS) :

    -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

Altre risposte mostrano come configurare globalmente i certificati client. Tuttavia, se si desidera definire a livello di programmazione la chiave del client per una particolare connessione, piuttosto che definirla a livello globale su tutte le applicazioni in esecuzione sulla propria JVM, è possibile configurare il proprio SSLContext in questo modo:

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"));

Il loro file JKS è solo un contenitore per certificati e coppie di chiavi. In uno scenario di autenticazione lato client, le varie parti delle chiavi si troveranno qui:

  • Lo store del cliente conterrà la coppia di chiavi privata e pubblica del client. Si chiama un keystore .
  • Lo store del server conterrà la chiave pubblica del client. Si chiama truststore .

La separazione di truststore e keystore non è obbligatoria ma consigliata. Possono essere lo stesso file fisico.

Per impostare le posizioni del filesystem dei due negozi, utilizzare le seguenti proprietà di sistema:

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

e sul server:

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

Per esportare il certificato del client (chiave pubblica) in un file, in modo da poterlo copiare sul server, utilizzare

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

Per importare la chiave pubblica del client nel keystore del server, utilizzare (come indicato nel poster, questo è già stato fatto dagli amministratori del server)

keytool -import -file publicclientkey.cer -store serversidestore.jks

Per quelli di voi che desiderano semplicemente impostare un'autenticazione a due vie (certificati server e client), una combinazione di questi due collegamenti vi porterà lì:

Configurazione dell'autorizzazione a due vie:

https://linuxconfig.org/apache-web-server-ssl-authentication

Non è necessario utilizzare il file di configurazione di openssl che menzionano; basta usare

  • $ openssl genrsa -des3 -out ca.key 4096

  • $ openssl req -new -x509 -giorni 365 -chiave ca.key -out ca.crt

per generare il proprio certificato CA, quindi generare e firmare le chiavi server e client tramite:

  • $ openssl genrsa -des3 -out server.key 4096

  • $ openssl req -new -key client.key -out server.csr

  • $ openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 100 -out server.crt

e

  • $ 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

Per il resto segui i passaggi del link. La gestione dei certificati per Chrome funziona come nell'esempio per firefox menzionato.

Quindi, configura il server tramite:

https://www.digitalocean.com/community/tutorials/how-to-create-a-ssl-certificate-on-apache-for-ubuntu-14-04

Nota che hai già creato il server .crt e .key in modo da non dover più fare quel passo.


Se vuoi provare la risposta con il maggior numero di voti sopra, puoi semplicemente usare questo codice:

public class Randomizer
{
    public static int generate(int min,int max)
    {
        return min + (int)(Math.random() * ((max - min) + 1));
    }

    public static void main(String[] args)
    {
        System.out.println(Randomizer.generate(0,10));
    }
}

È solo pulito e semplice.





java ssl https client-certificates