Come vengono risolti i nomi dei server dei certificati SSL / Posso aggiungere nomi alternativi usando keytool?

Questi possono essere formulati come domande separate per chiarezza, ma sono tutti legati allo stesso problema.

Come vengono risolti i nomi dei server di certificati SSL?

Perché i browser sembrano utilizzare il campo CN del certificato, ma il meccanismo di Java sembra guardare solo ai “nomi alternativi di sobject”?

È ansible aggiungere nomi alternativi a un certificato SSL usando keytool? Se no, sta usando openSSL invece una buona opzione ??

Solo un piccolo background: ho bisogno di ottenere un server principale per comunicare con diversi server usando HTTPS. Ovviamente, non vogliamo acquistare certificati SSL per ogni server (ce ne potrebbero essere molti), quindi voglio usare certificati autofirmati (ho usato keytool per generarli). Dopo aver aggiunto i certificati come affidabili nel sistema operativo, i browser (IE e Chrome) accettano felicemente la connessione come attendibile. Tuttavia, anche dopo aver aggiunto i certificati ai cacerts di Java, Java non accetterà la connessione come attendibile e lancia la seguente eccezione:

Causato da: java.security.cert.CertificateException: nessun nome alternativo di sobject presente su sun.security.util.HostnameChecker.matchIP (HostnameChecker.java:142) su sun.security.util.HostnameChecker.match (HostnameChecker.java:75) su com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkIdentity (X509T rustManagerImpl.java:264) su com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted (X509TrustManagerImpl.java:250) su com. sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate (Clien tHandshaker.java:1185) … 14 altri

Ho scoperto che posso rendere Java affidabile il certificato che implementa il mio HostNameVerifier, che ho copiato da qui: com.sun.jbi.internal.security.https.DefaultHostnameVerifier solo per testare (a proposito, il nome host passato come argomento al HostnameVerifier è corretto, quindi penso che avrebbe dovuto essere accettato).

Ho usato il campo del certificato CN come nome host (di solito l’indirizzo IP).

Qualcuno può dirmi se sto facendo qualcosa di sbagliato e indicarmi la giusta direzione?

Come deve essere eseguita la verifica del nome host è definito in RFC 6125 , che è abbastanza recente e generalizza la pratica a tutti i protocolli e sostituisce RFC 2818 , che era specifico per HTTPS. (Non sono nemmeno sicuro che Java 7 usi RFC 6125, che potrebbe essere troppo recente per questo.)

Da RFC 2818 (Sezione 3.1) :

Se è presente un’estensione subjectAltName di tipo dNSName, DEVE essere utilizzata come id quadro. In caso contrario, DEVE essere utilizzato il campo Nome comune (più specifico) nel campo Oggetto del certificato. Sebbene l’uso del nome comune sia una pratica esistente, è deprecato e le autorità di certificazione sono invece incoraggiate a utilizzare dNSName.

[…]

In alcuni casi, l’URI viene specificato come indirizzo IP anziché come nome host. In questo caso, iPAltrs subjectAltName deve essere presente nel certificato e deve corrispondere esattamente all’IP nell’URI.

In sostanza, il problema specifico deriva dal fatto che stai usando gli indirizzi IP nel tuo CN e non il nome di un host. Alcuni browser potrebbero funzionare perché non tutti gli strumenti seguono questa specifica in modo rigoroso, in particolare perché “più specifico” in RFC 2818 non è chiaramente definito (vedere le discussioni in RFC 6215).

Se stai usando keytool , come da Java 7, keytool ha un’opzione per includere un Nome alternativo sobject (vedi la tabella nella documentazione per -ext ): potresti usare -ext san=dns:www.example.com oppure -ext san=ip:10.0.0.1 .

MODIFICARE:

È ansible richiedere una SAN in OpenSSL modificando openssl.cnf (selezionerà la copia nella directory corrente se non si desidera modificare la configurazione globale, per quanto mi ricordo, oppure è ansible scegliere una posizione esplicita usando OPENSSL_CONF variabile d’ambiente).

Imposta le seguenti opzioni (trova prima le sezioni appropriate tra parentesi):

 [req] req_extensions = v3_req [ v3_req ] subjectAltName=IP:10.0.0.1 # or subjectAltName=DNS:www.example.com 

C’è anche un bel trucco per usare una variabile d’ambiente per questo (piuttosto che ripararlo in un file di configurazione) qui: http://www.crsr.net/Notes/SSL.html