Подтвердить что ты не робот

Android SSL - нет сертификата партнера

Всякий раз, когда этот код работает, я получаю ошибку "Нет равных сертификатов".

Сертификат 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)
4b9b3361

Ответ 1

Несмотря на то, что у этого вопроса есть принятый ответ, я подумал, что стоит ответить, так как я получил ту же ошибку на более раннем Android-устройстве под управлением 2.3.3:

javax.net.ssl.SSLPeerUnverifiedException: No peer certificate

Прочитав несколько разных связанных вопросов на SO, я пришел к выводу, что это может произойти по двум причинам (возможно, больше?):

  • Неверная установка промежуточного сертификата
  • Неверное упорядочение цепочки сертификатов

В моем случае это был неправильный порядок сертификатов. В качестве примера я отправляю сертификат из этого вопроса с проницательным ответом от пользователя 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/[email protected]
 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/[email protected]

Правило состоит в том, что эмитент сертификата "n" в цепочке должен соответствовать типу сертификата "n + 1".

Как только я нашел проблему, было тривиально изменить заказ сертификата на сервере, и все сразу начало работать на устройстве Android 2.3.3. Я думаю, это хорошо, что старые версии Android немного надоедливы по поводу заказа на сертификацию, но это был также кошмар, поскольку новые версии Android автоматически изменяют порядок сертификатов. Черт, даже старый iPhone 3GS работал с неактивными сертификатами.

Ответ 2

Этот белый документ может суммировать все, что вам нужно знать, чтобы заставить ваш SSL работать на Android. Основываясь на моем недавнем опыте, лучший подход - получить сертификат SSL, который нравится Android.

Ответ 3

Если это не проблема сервера, которая в большинстве случаев я видел эту проблему, она связана либо с отсутствующими промежуточными сертификатами, либо с плохой установкой сертификатов.

Попробуйте использовать реестр схем следующим образом:

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

Ответ 4

Проверьте системное время. Если время не текущее, это может привести к ошибке.

Ответ 5

На самом деле я пытаюсь сам диагностировать это сам сейчас, и, похоже, одна вещь может привести к этой проблеме, так это то, что сервер не работает или время соединения заканчивается.

Ответ 6

Я удаляю всех сотрудников реестра Scheme, и "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());

может быть, вы можете попробовать удалить те, которые у вас есть.

Ответ 7

Я попытался исправить это из кода Android, добавив правило "принять все сертификаты". Но все усилия со стороны андроида были бесполезны. Наконец, сделав CNAME в записи регистратора, который обеспечил, чтобы все запросы переходили на тот же IP-адрес, исправлена ​​проблема

Ответ 8

Убедитесь, что вы используете HttpsURLConnection вместо HttpURLConnection.

Ответ 9

Поскольку сертификат действителен, вы не должны использовать собственный SchemeRegistry, вы должны просто полагаться на механизм проверки подлинности по умолчанию по умолчанию.