Java7 Rifiutandosi di fidarsi del certificato nel trust store

Ho un problema strano: un fornitore utilizza TLS SSLv3 con un certificato autofirmato di client e server. Questo non è stato un problema con Java1.5 e Java1.6: è sufficiente importare il certificato client e la chiave privata in un keystore e il certificato pubblico del server nel truststore. Tutto funziona bene Tuttavia con Java7 il certificato del server non viene considerato affidabile anche se viene utilizzato lo stesso truststore. Ho provato Windows e Red Hat sia con Java7 (versioni 1.7.03, 04 e 05, x86 e x64) senza successo.

Ho ricreato il keystore / truststore da zero e contengono solo questi certificati. Le proprietà di sistema appropriate sono state impostate (javax.net.ssl.keyStore, javax.net.ssl.trustStore) e l’aspetto chiave è che esattamente lo stesso codice e la stessa configurazione funzionano perfettamente in JDK5 / 6.

Sono in perdita – Non riesco a trovare alcun riferimento al controllo aggiuntivo, ma avrei pensato che il fatto che il certificato si trovasse nel truststore dovrebbe significare che è affidabile, indipendentemente dal fatto che sia autofirmato.

Qualsiasi aiuto apprezzato. Annunci

Traccia delle eccezioni:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1868) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:276) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:270) at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1338) at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:154) at sun.security.ssl.Handshaker.processLoop(Handshaker.java:868) at sun.security.ssl.Handshaker.process_record(Handshaker.java:804) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:998) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1294) at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:685) at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:111) at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221) at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291) at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:295) at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141) at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229) at com.alltria.ypsilon.testing.TestSSL.main(TestSSL.java:65) Caused by: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:350) at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:249) at sun.security.validator.Validator.validate(Validator.java:260) at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:326) at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231) at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:126) at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1320) ... 13 more Caused by: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:208) at java.security.cert.CertPathValidator.validate(CertPathValidator.java:279) at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:345) ... 19 more Java Result: 1 

La parte in cui il debug di ssl non riesce sta tentando di convalidare il certificato del server:

 *** %% Invalidated: [Session-1, SSL_RSA_WITH_RC4_128_SHA] main, SEND SSLv3 ALERT: fatal, description = certificate_unknown main, WRITE: SSLv3 Alert, length = 2 [Raw write]: length = 7 0000: 15 03 00 00 02 02 2E ....... main, called closeSocket() main, handling exception: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors main, called close() main, called closeInternal(true) 

In realtà avevo un problema simile, in cui un’applicazione Tomcat si fidava del ca cert nel truststore quando utilizzava Java 1.6 e la rifiutava con java 1.7. Dopo aver aggiunto keyUsage al mio certificato keyUsage , funziona (dopo aver letto un bug report, JDK-7018897: la convalida di CertPath non può gestire il certificato autofirmato con KeyUsage errato ).

Cosa ho fatto (Ubuntu 12.04 x64):

  1. Modifica /etc/ssl/openssl.cnf e uncomment keyUsage line nella sezione v3_ca .
  2. Genera nuovo ca cert da uno vecchio con keyUsage incluso usando il comando:

     openssl x509 -in oldca.pem -clrext -signkey oldca.key -extfile /etc/ssl/openssl.cnf -extensions v3_ca -out newca.pem 
  3. Cancellare la vecchia chiave CA dal truststore e inserirne una nuova.

Ho anche riscontrato questa situazione quando ho a che fare con JDK 1.7. Se il comando req viene richiamato con l’opzione -x509, è meglio decommentare la riga keyUsage nella sezione v3_ca e generare nuovamente la CA con (vedere http://wwwneu.secit.at/web/documentation/openssl/openssl_cnf.html )

 openssl req -new -x509 -days 3650 -keyout ca.key -out ca.crt -config openssl.cnf -extensions v3_ca -batch 

E se utilizzi il certificato CA generato per firmare un altro certificato, assicurati di rimuovere anche il commento dall’elemento basicConstraints = CA: true e imposta il valore su true

Per alcuni motivi Java 8 non accetta certificati autofirmati anche aggiunti al proprio archivio cacerts .

La mia soluzione alternativa è quella di creare un keystore personalizzato:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -subj "/C=MA/ST=ByExample/L=Test/O=Chapter3/OU=Org/CN=bip70.com" -node s

 keytool -import -keystore clientkeystore -file cert.der -alias bip70.com -storepass changeit 

quindi utilizzandolo in My ID utilizzando come argomento jvm: -Djavax.net.ssl.trustStore=clientkeystore