18

Whenever this code runs, I get a 'No Peer Certificate' error.

SSL certificate is valid, bought from Namecheap (PositiveSSL). It has the CA crt before it, and opens fine in the Android browser.

HTTP server: nginx

Code:

public void postData() {

// Add your data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);

nameValuePairs.add(new BasicNameValuePair("string", "myfirststring"));

try {

   HttpPost post = new HttpPost(new URI("https://example.com/submit"));
    post.setEntity(new UrlEncodedFormEntity(nameValuePairs));

    KeyStore trusted = KeyStore.getInstance("BKS");
    trusted.load(null, "".toCharArray());
    SSLSocketFactory sslf = new SSLSocketFactory(trusted);
    sslf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

    SchemeRegistry schemeRegistry = new SchemeRegistry();
    schemeRegistry.register(new Scheme ("https", sslf, 443));
    SingleClientConnManager cm = new SingleClientConnManager(post.getParams(),
            schemeRegistry);

    HttpClient client = new DefaultHttpClient(cm, post.getParams());

    // Execute HTTP Post Request
    @SuppressWarnings("unused")
    HttpResponse result = client.execute(post);

} catch (ClientProtocolException e) {
    // TODO Auto-generated catch block
    Log.e(TAG,e.getMessage());
    Log.e(TAG,e.toString());
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    Log.e(TAG,e.getMessage());
    Log.e(TAG,e.toString());
    e.printStackTrace();
} catch (URISyntaxException e) {
        // TODO Auto-generated catch block
    Log.e(TAG,e.getMessage());
    Log.e(TAG,e.toString());
    e.printStackTrace();
    } catch (KeyStoreException e) {
        // TODO Auto-generated catch block
        Log.e(TAG,e.getMessage());
        Log.e(TAG,e.toString());
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        Log.e(TAG,e.getMessage());
        Log.e(TAG,e.toString());
        e.printStackTrace();
    } catch (CertificateException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        Log.e(TAG,e.toString());
        Log.e(TAG,e.getMessage());
    } catch (KeyManagementException e) {
        // TODO Auto-generated catch block
        Log.e(TAG,e.getMessage());
        Log.e(TAG,e.toString());
        e.printStackTrace();
    } catch (UnrecoverableKeyException e) {
        // TODO Auto-generated catch block
        Log.e(TAG,e.getMessage());
        Log.e(TAG,e.toString());
        e.printStackTrace();
    }
}

Adb logcat:

01-10 15:44:34.872: E/myfirstapp(572): No peer certificate
01-10 15:44:34.872: E/myfirstapp(572): javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
01-10 15:44:34.883: W/System.err(572): javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
01-10 15:44:34.883: W/System.err(572):  at org.apache.harmony.xnet.provider.jsse.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:137)
01-10 15:44:34.883: W/System.err(572):  at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:93)
01-10 15:44:34.908: W/System.err(572):  at org.apache.http.conn.ssl.SSLSocketFactory.createSocket(SSLSocketFactory.java:381)
01-10 15:44:34.908: W/System.err(572):  at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:165)
01-10 15:44:34.908: W/System.err(572):  at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
01-10 15:44:34.914: W/System.err(572):  at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
01-10 15:44:34.914: W/System.err(572):  at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
01-10 15:44:34.914: W/System.err(572):  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
01-10 15:44:34.914: W/System.err(572):  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
01-10 15:44:34.914: W/System.err(572):  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
01-10 15:44:34.933: W/System.err(572):  at com.giggsey.myfirstapp.myfirstappIntent.postData(myfirstappIntent.java:126)
01-10 15:44:34.933: W/System.err(572):  at com.giggsey.myfirstapp.myfirstappIntent.onReceive(myfirstappIntent.java:77)
01-10 15:44:34.933: W/System.err(572):  at android.app.ActivityThread.handleReceiver(ActivityThread.java:2118)
01-10 15:44:34.945: W/System.err(572):  at android.app.ActivityThread.access$1500(ActivityThread.java:122)
01-10 15:44:34.945: W/System.err(572):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
01-10 15:44:34.952: W/System.err(572):  at android.os.Handler.dispatchMessage(Handler.java:99)
01-10 15:44:34.952: W/System.err(572):  at android.os.Looper.loop(Looper.java:137)
01-10 15:44:34.962: W/System.err(572):  at android.app.ActivityThread.main(ActivityThread.java:4340)
01-10 15:44:34.962: W/System.err(572):  at java.lang.reflect.Method.invokeNative(Native Method)
01-10 15:44:34.962: W/System.err(572):  at java.lang.reflect.Method.invoke(Method.java:511)
01-10 15:44:34.972: W/System.err(572):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
01-10 15:44:34.972: W/System.err(572):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
01-10 15:44:34.981: W/System.err(572):  at dalvik.system.NativeStart.main(Native Method)
giggsey
  • 933
  • 2
  • 11
  • 31
  • 1
    Since certificate is valid, can you tried without your own SchemeRegistry, just relying on default android? – kenota Jan 10 '12 at 15:56
  • 3
    Use this page to test the certificate. I'm pretty sure that you are missing some intermediate certificates. https://www.digicert.com/help/index.htm That should let you know if this is a server related issue. Which I think it is. – blindstuff Jan 10 '12 at 15:57
  • @blindstuff All ticks from that page. – giggsey Jan 10 '12 at 15:58
  • 1
    I had this problem once, I got all ticks, but the page had a waring that said something like "The server is not sending all required intermediate certificates. Newer browsers will not complain, but some mobile devices will give warnings because this server needs to be sending one more intermediate certificate during SSL handshakes." – blindstuff Jan 10 '12 at 16:03
  • @kenota That was it. If you want to submit an answer, I'll mark it as the solution. – giggsey Jan 10 '12 at 16:04
  • THANK YOU BLINDSTUFF! I was going crazy trying to consume a REST api that I had no control of. This was extremely useful in locating the source of "No peer certificate". AGAIN THANK YOU! – Jim Jun 18 '13 at 12:35
  • Possible duplicate of [How do I avoid getting "No peer certificate" error when connecting to this HTTPS site on Android?](http://stackoverflow.com/questions/7583548/how-do-i-avoid-getting-no-peer-certificate-error-when-connecting-to-this-https) – Abhinav Saxena Jan 09 '17 at 07:44

9 Answers9

24

Even though this question has an accepted answer I thought it worthwhile to answer since I got the same error on an older Android device running 2.3.3:

javax.net.ssl.SSLPeerUnverifiedException: No peer certificate

After reading several different related questions on SO I came to the conclusion that this can happen for two (maybe more?) reasons:

  • Improper installation of an intermediate certificate
  • Incorrect ordering of the certificate chain

In my case it was an incorrect ordering of certificates. As an example I'm posting the cert order from this question with the insightful answer from user bdc. You can get the certificate ordering by doing the following from a terminal:

openssl s_client -connect eu.battle.net:443

(obviously replacing eu.battle.net with your own server). In the case of eu.battle.net at that time the order was:

Certificate chain
 0 s:/C=US/ST=California/L=Irvine/O=Blizzard Entertainment, Inc./CN=*.battle.net
   i:/C=US/O=Thawte, Inc./CN=Thawte SSL CA
 1 s:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA
   i:/C=ZA/ST=Western Cape/L=Cape Town/O=Thawte Consulting cc/OU=Certification Services Division/CN=Thawte Premium Server CA/emailAddress=premium-server@thawte.com
 2 s:/C=US/O=Thawte, Inc./CN=Thawte SSL CA
   i:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA

While it should have been:

Certificate chain
 0 s:/C=US/ST=California/L=Irvine/O=Blizzard Entertainment, Inc./CN=*.battle.net
   i:/C=US/O=Thawte, Inc./CN=Thawte SSL CA
 1 s:/C=US/O=Thawte, Inc./CN=Thawte SSL CA
   i:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA
 2 s:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA
   i:/C=ZA/ST=Western Cape/L=Cape Town/O=Thawte Consulting cc/OU=Certification Services Division/CN=Thawte Premium Server CA/emailAddress=premium-server@thawte.com

The rule is that the issuer of cert "n" in the chain should match the subject of cert "n+1".

Once I found the problem it was trivial to change the cert order on the server and things immediately started working on the Android 2.3.3 device. I guess it's good that older Android versions are a bit pesky about cert order, but it was also a nightmare since newer Android versions reorder the certs automatically. Hell, even an old iPhone 3GS worked with certs out of order.

Community
  • 1
  • 1
britzl
  • 10,132
  • 7
  • 41
  • 38
  • Thank you for this answer. I had the certificate ordering issue and it was driving me crazy -- apparently SOME versions of android accept certificates in the wrong order, and some don't. – Ricardo Massaro Jul 05 '13 at 18:14
  • Ditto for me, rapidssl issued certs were backwards, all browsers worked but my app was failing. When I reordered the certs everything worked. Thanks very much! – mvsjes2 Aug 19 '13 at 04:08
  • Upvoted. I tried many different methods of keytool and bouncycastle trusted keystores but in the end, Android 2.3 simply didn't like not having the intermediate cert in my server's ssl chain. Neither Android Jellybean, Firefox, IE or Chrome complained - only Android 2.3 DefaultHTTPClient. After adding the gd_intermediate.crt, my GB app worked over SSL. See here for details:http://informationideas.com/news/2011/11/29/android-making-https-requests-with-ssl-from-godaddy-no-peer-certificate-error/ – wufoo Jan 30 '14 at 15:07
3

If it is not a Server issue, which in most cases that I have seen this issue it is related to either missing intermediate certs or bad a install of the certs.

Try using the Scheme Registry like this:

SchemeRegistry schReg = new SchemeRegistry();
schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schReg.register(new Scheme("https",SSLSocketFactory.getSocketFactory(), 443));
SingleClientConnManager conMgr = new SingleClientConnManager(params,post.getParams());
blindstuff
  • 18,298
  • 10
  • 47
  • 48
  • 3
    I used `mClient = new DefaultHttpClient(); mClient.getConnectionManager().getSchemeRegistry().register(new Scheme("SSLSocketFactory", SSLSocketFactory.getSocketFactory(), 443));` and it worked. Thanks! – shkschneider Nov 05 '12 at 17:46
  • @shkschneider, you're my hero! – sha256 Aug 24 '13 at 16:14
  • 2
    @shkschneider... i also tried this line with my HttpClient but its giving me the same error "No Peer Certificate"... i am sending JSON params with https request... Please help me – Noman Sep 10 '13 at 10:59
1

Check your system time.If the time is not current time may cause this error.

robam
  • 11
  • 1
1

I have just recently gone through this problem. It wasn't the chain order that was the problem, but I have had that before.

What was the issue was that the server only accepts TLS1.2 socket connections. android 19 and lower default socket connection is TLS1 SSLSocket Docs

With the help of Enable TLS 1.2 in Android 4.4 I was able to get this to work. The question description worked for me. But please ensure that you do have the answer code in you application

Lawgrin Foul
  • 308
  • 2
  • 10
0

I'm actually trying to diagnose this myself right now, and it appears one thing that may cause this issue is that the server is down or the connection times out.

StackOverflowed
  • 5,854
  • 9
  • 55
  • 119
0

I remove all the Scheme Registry staff and the "No peer Certification error" is solved.

ie.

I remove this code from mine

SchemeRegistry schReg = new SchemeRegistry();
schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schReg.register(new Scheme("https",SSLSocketFactory.getSocketFactory(), 443));
SingleClientConnManager conMgr = new SingleClientConnManager(params,post.getParams());

may be you can try remove those from yours.

Krit
  • 610
  • 1
  • 7
  • 18
0

I tried to fix this from android code by adding an "accept all certificate" rule. But all the effort from android side was worthless. Finally making a CNAME in registrar entry that ensured that all requests go to the same IP address fixed the problem

0

Make sure you are using HttpsURLConnection instead of HttpURLConnection.

Ajji
  • 3,068
  • 2
  • 30
  • 31
-1

Because certificate is valid you should not use custom SchemeRegistry, you should just rely on default android certificate validation mechanism.

kenota
  • 5,640
  • 1
  • 15
  • 11