Question

I have a problem verifying Verisign certificate when trying to connect with HttpsURLConnection to our backend.

Current certification chain: $openssl s_client -connect host:443

0 s:/C=AT/ST=xxx/L=xxx/O=xxx/CN=host
   i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)10/CN=VeriSign Class 3 International Server CA - G3

1 s:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)10/CN=VeriSign Class 3 International Server CA - G3
   i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Auth
ority - G5

2 s:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Auth
ority - G5
   i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority

3 s:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority
   i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority

I'm pretty sure i have downloaded and added all certificates into KeyStore, but i still get exception : "javax.net.ssl.SSLException: Not trusted server certificate" and the cause is java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: TrustAnchor found but certificate validation failed.

My code for obtaining the connection:

String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("verisign_0", getVerisign0());
keyStore.setCertificateEntry("verisign_1", getVerisign1());
keyStore.setCertificateEntry("verisign_2", getVerisign2());
keyStore.setCertificateEntry("verisign_3", getVerisign3());

String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);

SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);

HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
return urlConnection;

issue is happening, when connection.connect() is called. All getVerisign() methods returns correct certificates. Is there a step I have forgotten? Maybe a special order in which the certificates should be added?

Just to clarify, I have used exactly this technique with swisssign certificates and it worked. I'm facing this issue because some of Android 2.1, 2.2 devices does not have some root certificates. Thanks in advance.

StackTrace:

[0] = {java.lang.StackTraceElement@830078967208}"org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:168)"
[1] = {java.lang.StackTraceElement@830078967584}"org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:366)"
[2] = {java.lang.StackTraceElement@830078967960}"org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.getSecureSocket(HttpConnection.java:168)"
[3] = {java.lang.StackTraceElement@830078968368}"org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:399)"
[4] = {java.lang.StackTraceElement@830078968816}"org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:147)"
Was it helpful?

Solution

Without further code I can not tell but, I can see you loading the Trusted Certs, but where are you loading your own Keystore? If it is in other code, I can not tell.

Also what happens when you try using an external Truststore e.g. $JAVA_HOME/jre/lib/security/cacerts

Assuming you really want to use a dynamic trust store (usually they are pretty static), have a look at

http://jcalcote.wordpress.com/2010/06/22/managing-a-dynamic-java-trust-store/

OTHER TIPS

As said before, the TrustStore inside the JVM is static, once initialized, certificates cannot be appended to it (as I observed with a similar problem). The simple solution is to add your certificates to the default one : $JAVA_HOME/jre/lib/security/cacerts

Or try to include your TrustStore initialization code into a static {} block to initialize it sooner and get a chance to bypass the default behavior.

You can also use a custom file KeysStore and ask the jvm to use it with the -Djavax.net.ssl.keyStore* parameters.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top