I created a java keystore with name cloudsslkeystore.jks
keytool -genkeypair -validity 730 -alias cloudsslkey -keystore cloudsslkeystore.jks -dname "cn=localhost" -keypass password -storepass password
I exported it as certificate with name cloudcertificate.cer
keytool -export -rfc -keystore cloudsslkeystore.jks -alias cloudsslkey -file cloudcertificate.cer
Enter keystore password:password
Certificate stored in file <cloudcertificate.cer>
I added the certificate cloudcertificate.cer to my local java security folder
C:\Program Files\Java\jre7\lib\security>keytool -keystore cacerts -importcert -noprompt -trustcacerts -alias cloudsslkey -file cloudcertificate.cer
Enter keystore password:changeit
Certificate was added to keystore
Now I used the same java keystore cloudsslkeystore.jks in tomcat server of a different machine by modifying server.xml
<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" keystoreFile="c:\keytool\cloudsslkeystore.jks" keystorePass="password" />
When I try to hit a webservice thru a java client, I get this exception.
Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: Problem writing SAAJ model to stream: sun.security.validator.ValidatorException: PKIX
path validation failed: java.security.cert.CertPathValidatorException: signature check failed
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:159)
at com.sun.proxy.$Proxy39.getAllRecommendations(Unknown Source)
at client.WSClient.main(WSClient.java:73)
Caused by: com.ctc.wstx.exc.WstxIOException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValida
torException: signature check failed
at com.ctc.wstx.sw.BaseStreamWriter.writeCharacters(BaseStreamWriter.java:458)
at org.apache.cxf.staxutils.StaxUtils.copy(StaxUtils.java:749)
at org.apache.cxf.staxutils.StaxUtils.copy(StaxUtils.java:696)
at org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor$SAAJOutEndingInterceptor.handleMessage(SAAJOutInterceptor.java:214)
at org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor$SAAJOutEndingInterceptor.handleMessage(SAAJOutInterceptor.java:174)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:307)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:514)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:423)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:326)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:279)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:137)
... 2 more
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathVal
idatorException: signature check failed
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1884)
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:1341)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:153)
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:1016)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1339)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1323)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1091)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:250)
at org.apache.cxf.transport.http.URLConnectionHTTPConduit$URLConnectionWrappedOutputStream.setupWrappedStream(URLConnectionHTTPConduit.java:17
4)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleHeadersTrustCaching(HTTPConduit.java:1302)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.onFirstWrite(HTTPConduit.java:1258)
at org.apache.cxf.transport.http.URLConnectionHTTPConduit$URLConnectionWrappedOutputStream.onFirstWrite(URLConnectionHTTPConduit.java:201)
at org.apache.cxf.io.AbstractWrappedOutputStream.write(AbstractWrappedOutputStream.java:47)
at org.apache.cxf.io.AbstractThresholdOutputStream.unBuffer(AbstractThresholdOutputStream.java:89)
at org.apache.cxf.io.AbstractThresholdOutputStream.write(AbstractThresholdOutputStream.java:63)
at org.apache.cxf.io.CacheAndWriteOutputStream.write(CacheAndWriteOutputStream.java:80)
at org.apache.cxf.io.AbstractWrappedOutputStream.write(AbstractWrappedOutputStream.java:51)
at com.ctc.wstx.io.UTF8Writer.write(UTF8Writer.java:143)
at com.ctc.wstx.sw.BufferingXmlWriter.writeRaw(BufferingXmlWriter.java:285)
at com.ctc.wstx.sw.BufferingXmlWriter.writeCharacters(BufferingXmlWriter.java:603)
at com.ctc.wstx.sw.BaseStreamWriter.writeCharacters(BaseStreamWriter.java:456)
... 13 more
Caused by: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: signature check fail
ed
at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:350)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:260)
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:1323)
... 37 more
Caused by: java.security.cert.CertPathValidatorException: signature check failed
at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:159)
at sun.security.provider.certpath.PKIXCertPathValidator.doValidate(PKIXCertPathValidator.java:351)
at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:191)
at java.security.cert.CertPathValidator.validate(CertPathValidator.java:279)
at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:345)
... 43 more
Caused by: java.security.SignatureException: Signature does not match.
at sun.security.x509.X509CertImpl.verify(X509CertImpl.java:451)
at sun.security.provider.certpath.BasicChecker.verifySignature(BasicChecker.java:160)
at sun.security.provider.certpath.BasicChecker.check(BasicChecker.java:139)
at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:133)
... 47 more
The Signature does not match
error is the symptom that the server identity is unknown to the client, ie the client truststore does not have the server certificate.
Create the server certificate and add it to a keystore:
keytool -genkey -noprompt -alias "$alias" -dname "CN=$dname_cn, OU=$dname_ou, O=$dname_o, L=$dname_l, S=$dname_s, C=$dname_c" -keystore "$keystore" -storepass "$storepass" -keypass "$keypass"
and export it for the client into a truststore:
keytool -export -alias "$alias" -storepass "$storepass" -file "$alias".cer -keystore "$keystore"
If you want 2-way SSL then you have to repeat this twice, inverting, they both must know each other.
Now the tricky part is to build an SSLContext
correctly and configure your client and server with it.
In Grizzly I do:
SSLContextConfigurator sslContextConfigurator = new SSLContextConfigurator();
// set up security context
sslContextConfigurator.setKeyStoreFile(configuration.getKeystore()); // contains the server keypair
sslContextConfigurator.setKeyStorePass(configuration.getKeystorePassword());
sslContextConfigurator.setKeyStoreType(configuration.getKeystoreType());
sslContextConfigurator.setKeyPass(configuration.getKeystoreKeypass());
sslContextConfigurator.setTrustStoreFile(configuration.getTruststore()); // contains the list of trusted certificates
sslContextConfigurator.setTrustStorePass(configuration.getTruststorePassword());
sslContextConfigurator.setTrustStoreType(configuration.getTruststoreType());
if (!sslContextConfigurator.validateConfiguration(true))
throw new Exception("Invalid SSL configuration");
For advanced debugging do not forget System.setProperty("javax.net.debug", "all");