Centaur Tech

Dips

Friday, May 22

1-way ssl setup and cert issues

1-way SSL overview :
 
1-way ssl requires that the client verifies the servers identity , and the server accepts any client request.
When the client sends a server request, the server presents a certificate to the client , and the client verifies the identity of the serverand proceeds if succesful.
For this to happen, the server needs to install certificate and private key on the server, while the client just needs to maintain the corresponding CA certificate (in truststore mostly).
The client truststore location can be specified using system property :
System.setProperty("javax.net.ssl.trustStore", "C:/CIBTAPPS/MyTrust.jks");
 
You might need to download the certificate(download in browser and 'export' as file) and import it in a truststore : 
Use keytool utility from the jdk as follows :
keytool -import -alias csw.dev.wachovia.net -file C:\CIBTAPPS\SSL.crt -keystore C:\CIBTAPPS\MyTrust.jks
 
List the certstore content as follows :
keytool -list -keystore c:\CIBTAPPS\WachoviaTrust.jks
Enter keystore password:  ****
Result will look something like :
Keystore type: jks
Keystore provider: SUN
 
Your keystore contains 2 entries
 
wachovia test ca, Aug 20, 2007, trustedCertEntry,
Certificate fingerprint (MD5): AE:72:8D:E0:55:FA:F4:77:C2:8F:5D:B1:D3:A5:A0:51
enterpriseca, Aug 31, 2007, trustedCertEntry,
Certificate fingerprint (MD5): A3:AC:32:B3:8B:75:96:D9:48:16:46:39:21:C7:3E:0C
myprivateroot, May 19, 2009, trustedCertEntry
 
Troubleshooting :
 
Problem :
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
 at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:150)
 at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1518)
 at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:174)
 at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:168)
 at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:848)
 at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:106)
 at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:495)
 at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:433)
 at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:818)
 at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1030)
 at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1057)
 at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1041)
 at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:402)
 at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:170)
 at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:861)
 at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:230)
 at org.springframework.ws.transport.http.HttpUrlConnection.getRequestOutputStream(HttpUrlConnection.java:82)
 at org.springframework.ws.transport.AbstractSenderConnection$RequestTransportOutputStream.createOutputStream(AbstractSenderConnection.java:101)
 at org.springframework.ws.transport.TransportOutputStream.getOutputStream(TransportOutputStream.java:41)
 at org.springframework.ws.transport.TransportOutputStream.write(TransportOutputStream.java:60)
 at com.sun.xml.messaging.saaj.soap.MessageImpl.writeTo(MessageImpl.java:1221)
 at org.springframework.ws.soap.saaj.Saaj13Implementation.writeTo(Saaj13Implementation.java:288)
 at org.springframework.ws.soap.saaj.SaajSoapMessage.writeTo(SaajSoapMessage.java:119)
 at org.springframework.ws.transport.AbstractWebServiceConnection.send(AbstractWebServiceConnection.java:42)
 at org.springframework.ws.client.core.WebServiceTemplate.sendRequest(WebServiceTemplate.java:549)
 at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:512)
 at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:465)
 ... 23 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
 at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:221)
 at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:145)
 at sun.security.validator.Validator.validate(Validator.java:203)
 at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:172)
 at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(SSLContextImpl.java:320)
 at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:841)
 ... 45 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
 at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:236)
 at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:194)
 at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:216)
 ... 50 more

Possible solutions :
Set the system property to appropriate keystore : System.setProperty("javax.net.ssl.trustStore", "C:/CIBTAPPS/MyTrust.jks");
If this is already set, the certificate might not exist in the store. Use keytool list to check the same.
 
Problem :
Caused by: java.io.IOException: HTTPS hostname wrong: should be <nc-sils-f5c-ict01-1wlg-weblogic-sit.test.wachovia.net>
at sun.net.www.protocol.https.HttpsClient.checkURLSpoofing(HttpsClient.java:490)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:415)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:170)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:861)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:230)
at org.springframework.ws.transport.http.HttpUrlConnection.getRequestOutputStream(HttpUrlConnection.java:82)
at org.springframework.ws.transport.AbstractSenderConnection$RequestTransportOutputStream.createOutputStream(AbstractSenderConnection.java:101)
at org.springframework.ws.transport.TransportOutputStream.getOutputStream(TransportOutputStream.java:41)
at org.springframework.ws.transport.TransportOutputStream.write(TransportOutputStream.java:60)
at com.sun.xml.messaging.saaj.soap.MessageImpl.writeTo(MessageImpl.java:1221)
at org.springframework.ws.soap.saaj.Saaj13Implementation.writeTo(Saaj13Implementation.java:288)
at org.springframework.ws.soap.saaj.SaajSoapMessage.writeTo(SaajSoapMessage.java:119)
at org.springframework.ws.transport.AbstractWebServiceConnection.send(AbstractWebServiceConnection.java:42)
at org.springframework.ws.client.core.WebServiceTemplate.sendRequest(WebServiceTemplate.java:549)
at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:512)
at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:465)... 25 more
 
Possible solutions :
The client also verifies hostname aka if the Cert Subject Distinguished Name (DN) contain a Common Name (CN) that exactly matches the hostname in the Web Service URL?
For example, a Web Service hosted at https://www.mycompany.com/services should be protected by an SSL certificate with a CN ofwww.mycompany.com .
In case of mismatch the above exception is seen. You need to have the right certificate with matching url and cn name.
There is no easy way to turn off hostname verification at the webservice client level. Programatically , it can be done as specified here : http://www.theserverside.com/discussions/thread.tss?thread_id=34538

Dips at 5:52 AM

1 comments

x.509 issue

Trying to generate an x509 certificate object from a byte stream :

    byte[] certBytes = (byte[]) certificatestring.getBytes();

    ByteArrayInputStream bin = new ByteArrayInputStream(certBytes);

    CertificateFactory cf = CertificateFactory.getInstance("X.509");

    X509Certificate certificate = (X509Certificate) cf.generateCertificate(bin);

It was giving me following exception :

java.security.cert.CertificateParsingException: invalid DER-encoded certificate data
 at sun.security.x509.X509CertImpl.parse(X509CertImpl.java:1680)
 at sun.security.x509.X509CertImpl.(X509CertImpl.java:303)
 at sun.security.provider.X509Factory.engineGenerateCertificate(X509Factory.java:104)
 at java.security.cert.CertificateFactory.generateCertificate(CertificateFactory.java:271)
The same certificate if I loaded from a saved .cer file, was working perfectly fine. It seemed like it was an issue with different kind of input streams. I checked for source code (thank heavens for open source !) at http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Modules-sun/security/sun/security/provider/X509Factory.java.htm and it seemed that there are 2 types of encoding it expects :
Base64 - if the inputstream starts with "-----BEGIN"
DER - if does not starts with above.
 
The bytestream which I had read from ldap needed to be appended with "-----BEGIN CERTIFICATE-----\n" and at the end with "\n-----END CERTIFICATE-----"
The certstring looked something like (valid one):
-----BEGIN CERTIFICATE-----
MIICYDCCAgqgAwIBAgIQBuJwHCWs3BMk7g16aheAGDANBgkqhkiG9w0BAQQFADBP
MSIwIAYDVQQKExlGaXJzdCBVbmlvbiBOYXRpb25hbCBCYW5rMSkwJwYDVQQLEyBD
b21tZXJjaWFsIENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw05OTA5MTIwMDAwMDBa
Fw0wMDA5MTEyMzU5NTlaMIGZMSIwIAYDVQQKFBlGaXJzdCBVbmlvbiBOYXRpb25h
bCBCYW5rMSkwJwYDVQQLFCBDb21tZXJjaWFsIENlcnRpZmljYXRlIEF1dGhvcml0
eTEYMBYGA1UECxMPVVNFUklEIC0gd2xmYWRtMRYwFAYDVQQDEw13bGZhZG0gd2xm
YWRtMRYwFAYJKoZIhvcNAQkBFgdpQGkubmV0MIGfMA0GCSqGSIb3DQEBAQUAA4GN
ADCBiQKBgQDC8Y/pbxTPmCd+eEyXWtMnlBhXwGbTyc41VQd3g74jn31AvFFJ3f9P
0ZFw+rN2+IP2nUhn2EfyzskY7P7VsohKRCXxoovMSeIdXib3414S6jfhRXCMbUdA
PNQi5TyByfSKaf/VBwypufU52ERq/pBzpm2ktREii7btmt+8I109wwIDAQABozMw
MTAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIHgDARBgpghkgBhvhFAQYJBAMB
Af8wDQYJKoZIhvcNAQEEBQADQQCjF+Vy7JHEIVAasDnw62j3hi6FhgDRVOgaEEbb
BoaGVCSAAibNX4V02b+LOfDYXaJVpipFEiYiX5QE+Eht0i/s
-----END CERTIFICATE-----
This should create that x509 object for you in a ziffy !

Dips at 5:51 AM

0 comments