Android SSL - 无对等证书

时间:2012-01-10 15:51:11

标签: android ssl

每当此代码运行时,我都会收到“No Peer Certificate”错误。

SSL证书有效,从Namecheap(PositiveSSL)购买。它之前有CA crt,并且在Android浏览器中打开正常。

HTTP服务器:nginx

代码:

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)

10 个答案:

答案 0 :(得分:21)

即使这个问题有一个公认的答案,我认为值得回答,因为我在运行2.3.3的旧设备上遇到了同样的错误:

javax.net.ssl.SSLPeerUnverifiedException: No peer certificate

在阅读了几个关于SO的不同相关问题后,我得出的结论是,这可能发生在两个(可能更多?)的原因上:

  • 中间证书安装不当
  • 证书链的排序不正确

在我的情况下,证书的排序不正确。作为示例,我使用来自用户this question的深刻答案从bdc发布证书订单。您可以通过终端执行以下操作来获取证书订购:

openssl s_client -connect eu.battle.net:443

(显然用你自己的服务器取代eu.battle.net)。在eu.battle.net的情况下,订单是:

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

虽然应该是:

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

规则是链中证书“n”的发行者应与证书“n + 1”的主题相匹配。

一旦我发现问题,更改服务器上的证书顺序是微不足道的,并且事情立即开始在Android 2.3.3设备上运行。我认为旧的Android版本对于证书订单有点麻烦,但这也是一个噩梦,因为较新的Android版本会自动重新排序证书。地狱,即使是旧版的iPhone 3GS也无法使用证书。

答案 1 :(得分:3)

white paper可能会总结您需要了解的所有内容,以使您的SSL在Android上运行。根据我最近的经验,最好的方法是获得Android喜欢的SSL证书。

答案 2 :(得分:2)

如果它不是服务器问题,在大多数情况下,我已经看到了这个问题,它与缺少中间证书或安装证书有关。

尝试使用Scheme注册表:

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());

答案 3 :(得分:1)

检查系统时间。如果时间不是当前时间可能会导致此错误。

答案 4 :(得分:0)

我现在正在尝试自己诊断这一点,并且可能导致此问题的一件事是服务器关闭或连接超时。

答案 5 :(得分:0)

我删除了所有Scheme Registry员工,并解决了“No peer Certification error”。

即。

我从我的

中删除了此代码
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());

可能是你可以尝试删除你的那些。

答案 6 :(得分:0)

我尝试通过添加&#34;接受所有证书&#34;来解决这个问题。规则。但是android方面的所有努力都毫无价值。 最后在注册商条目中创建一个CNAME,确保所有请求都转到相同的IP地址来解决问题

答案 7 :(得分:0)

确保您使用HttpsURLConnection代替HttpURLConnection

答案 8 :(得分:0)

我刚刚遇到这个问题。 链序不是问题,但我之前已经有了。

问题是服务器只接受TLS1.2套接字连接。 android 19和更低的默认套接字连接是TLS1 SSLSocket Docs

Enable TLS 1.2 in Android 4.4的帮助下,我能够让它发挥作用。问题描述对我有用。但请确保您的应用程序中有答案代码

答案 9 :(得分:-1)

因为证书有效,所以你不应该使用自定义SchemeRegistry,你应该只依赖默认的android证书验证机制。