Note that there are some explanatory texts on larger screens.

plurals
  1. POApache HttpClient on Android producing CertPathValidatorException (IssuerName != SubjectName)
    text
    copied!<p>I'm developing an Android application for accessing some battle.net (<a href="https://eu.battle.net" rel="noreferrer">https://eu.battle.net</a>) account data (for World of Warcraft) and I'm using the <code>org.apache.http.client.HttpClient</code> to do so.</p> <p>This is the code I'm using:</p> <pre><code> public static final String USER_AGENT = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 (.NET CLR 3.5.30729)"; public static class MyHttpClient extends DefaultHttpClient { final Context context; public MyHttpClient(Context context) { super(); this.context = context; } @Override protected ClientConnectionManager createClientConnectionManager() { SchemeRegistry registry = new SchemeRegistry(); registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); // Register for port 443 our SSLSocketFactory with our keystore // to the ConnectionManager registry.register(new Scheme("https", newSslSocketFactory(), 443)); return new SingleClientConnManager(getParams(), registry); } private SSLSocketFactory newSslSocketFactory() { try { // Get an instance of the Bouncy Castle KeyStore format KeyStore trusted = KeyStore.getInstance("BKS"); // Get the raw resource, which contains the keystore with // your trusted certificates (root and any intermediate certs) InputStream in = context.getResources().openRawResource(R.raw.battlenetkeystore); try { // Initialize the keystore with the provided trusted certificates // Also provide the password of the keystore trusted.load(in, "mysecret".toCharArray()); } finally { in.close(); } // Pass the keystore to the SSLSocketFactory. The factory is responsible // for the verification of the server certificate. SSLSocketFactory sf = new SSLSocketFactory(trusted); // Hostname verification from certificate // http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506 sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER); return sf; } catch (Exception e) { throw new AssertionError(e); } } } private static void maybeCreateHttpClient(Context context) { if (mHttpClient == null) { mHttpClient = new MyHttpClient(context); final HttpParams params = mHttpClient.getParams(); HttpConnectionParams.setConnectionTimeout(params, REGISTRATION_TIMEOUT); HttpConnectionParams.setSoTimeout(params, REGISTRATION_TIMEOUT); ConnManagerParams.setTimeout(params, REGISTRATION_TIMEOUT); Log.d(TAG, LEAVE + "maybeCreateHttpClient()"); } } public static boolean authenticate(String username, String password, Handler handler, final Context context) { final HttpResponse resp; final ArrayList&lt;NameValuePair&gt; params = new ArrayList&lt;NameValuePair&gt;(); params.add(new BasicNameValuePair(PARAM_USERNAME, username)); params.add(new BasicNameValuePair(PARAM_PASSWORD, password)); HttpEntity entity = null; try { entity = new UrlEncodedFormEntity(params); } catch (final UnsupportedEncodingException e) { // this should never happen. throw new AssertionError(e); } final HttpPost post = new HttpPost(THE_URL); post.addHeader(entity.getContentType()); post.addHeader("User-Agent", USER_AGENT); post.setEntity(entity); maybeCreateHttpClient(context); if (mHttpClient == null) { return false; } try { resp = mHttpClient.execute(post); } catch (final IOException e) { Log.e(TAG, "IOException while authenticating", e); return false; } finally { } } </code></pre> <p>The keystore is retrieved (by OpenSSL) like this:</p> <pre><code>openssl s_client -connect eu.battle.net:443 -showcerts </code></pre> <p>I have compared the certificates that command produced (<a href="http://vipsaran.webs.com/openssl_output.txt" rel="noreferrer">http://vipsaran.webs.com/openssl_output.txt</a>) with ones I exported from Firefox (<a href="http://vipsaran.webs.com/Firefox_output.zip" rel="noreferrer">http://vipsaran.webs.com/Firefox_output.zip</a>) and they are the same.</p> <p>By following advice on <a href="http://blog.antoine.li/index.php/2010/10/android-trusting-ssl-certificates/" rel="noreferrer">this blog</a>, I have setup the above code and imported the (root and intermediate) certs to a keystore (battlenetkeystore.bks) which is used for HttpClient.</p> <p>This are the commands I used for importing the certs to the keystore:</p> <pre><code>keytool -importcert -v -file ~/lib/ThawteSSLCA.crt -alias thawtesslca -keystore ~/lib/battlenetkeystore.bks -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath ~/lib/bcprov-jdk16-145.jar -storetype BKS -storepass mysecret -keypass mysecret -keyalg "RSA" -sigalg "SHA1withRSA" keytool -importcert -v -file ~/lib/thawtePrimaryRootCA.crt -alias thawteprimaryrootca -keystore ~/lib/battlenetkeystore.bks -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath ~/lib/bcprov-jdk16-145.jar -storetype BKS -storepass mysecret -keypass mysecret -keyalg "RSA" -sigalg "SHA1withRSA" </code></pre> <p>Btw. I have also tried <code>keytool -import</code> without the <code>-keyalg "RSA" -sigalg "SHA1withRSA"</code>, but with no change.</p> <p><strong>The problem</strong> is that I'm getting this error:</p> <pre><code>javax.net.ssl.SSLException: Not trusted server certificate at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:371) at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:92) at org.apache.http.conn.ssl.SSLSocketFactory.createSocket(SSLSocketFactory.java:381) at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:164) at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164) at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119) at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:348) at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555) at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487) at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465) at org.homedns.saran.android.wowcalendarsync.network.NetworkUtilities.authenticateWithPass(NetworkUtilities.java:346) at org.homedns.saran.android.wowcalendarsync.network.NetworkUtilities$1.run(NetworkUtilities.java:166) at org.homedns.saran.android.wowcalendarsync.network.NetworkUtilities$5.run(NetworkUtilities.java:278) Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: IssuerName(CN=thawte Primary Root CA, OU="(c) 2006 thawte, Inc. - For authorized use only", OU=Certification Services Division, O="thawte, Inc.", C=US) does not match SubjectName(CN=Thawte SSL CA, O="Thawte, Inc.", C=US) of signing certificate at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:168) at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:366) ... 12 more Caused by: java.security.cert.CertPathValidatorException: IssuerName(CN=thawte Primary Root CA, OU="(c) 2006 thawte, Inc. - For authorized use only", OU=Certification Services Division, O="thawte, Inc.", C=US) does not match SubjectName(CN=Thawte SSL CA, O="Thawte, Inc.", C=US) of signing certificate at org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi.engineValidate(PKIXCertPathValidatorSpi.java:373) at java.security.cert.CertPathValidator.validate(CertPathValidator.java:202) at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:164) ... 13 more </code></pre> <p>and I can't figure a way to solve it. Tried importing the certs into the keystore in different order, aso. but nothing worked.</p> <p><strong>Please help</strong> (and please focus on the solutions based on the Android's Apache HttpClient <em>only</em>).</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload