web-dev-qa-db-fra.com

Android SSL - Pas de certificat de pair

Chaque fois que ce code est exécuté, le message d'erreur «Aucun certificat homologue» s'affiche.

Le certificat SSL est valide, acheté à Namecheap (PositiveSSL). Il est précédé du code CA et s'ouvre correctement dans le navigateur Android.

Serveur HTTP: 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)
16
giggsey

Même si cette question a une réponse acceptée, j'ai pensé qu'il valait la peine de répondre car j'ai la même erreur sur un ancien appareil Android fonctionnant sous 2.3.3:

javax.net.ssl.SSLPeerUnverifiedException: No peer certificate

Après avoir lu plusieurs questions connexes sur SO, je suis parvenue à la conclusion que cela pouvait se produire pour deux raisons (peut-être plus?):

  • Mauvaise installation d'un certificat intermédiaire
  • Commande incorrecte de la chaîne de certificats

Dans mon cas, c’était une mauvaise commande de certificats. Par exemple, je poste la commande de cert de cette question avec la réponse perspicace de l’utilisateur bdc . Vous pouvez obtenir la commande de certificat en procédant comme suit depuis un terminal:

openssl s_client -connect eu.battle.net:443

(évidemment remplacer eu.battle.net par votre propre serveur). Dans le cas de eu.battle.net à cette époque, la commande était la suivante:

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

Alors que cela aurait dû être:

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]

La règle est que l'émetteur du certificat "n" de la chaîne doit correspondre à l'objet du certificat "n + 1".

Une fois que j'ai trouvé le problème, il était facile de modifier l'ordre du certificat sur le serveur et tout a immédiatement commencé à fonctionner sur le périphérique Android 2.3.3. Je suppose que c’est bien que les anciennes versions d’Android soient un peu gênantes au sujet de la commande cert, mais c’était aussi un cauchemar puisque les nouvelles versions d’Android réorganisent automatiquement les certificats. Bon sang, même un vieil iPhone 3GS fonctionnait mal avec les certificats.

21
britzl

Ce livre blanc peut résumer tout ce que vous devez savoir pour que votre SSL fonctionne sur Android. Sur la base de mon expérience récente, la meilleure approche consiste à obtenir un certificat SSL apprécié par Android.

3
Yong Qu

S'il ne s'agit pas d'un problème de serveur qui, dans la plupart des cas, j'ai vu ce problème est lié à des certificats intermédiaires manquants ou à une mauvaise installation des certificats.

Essayez d’utiliser le registre de schémas comme ceci:

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

Vérifiez l'heure de votre système. Si l'heure n'est pas à l'heure actuelle, cette erreur peut être causée.

1
robam

Je viens tout juste de passer en revue ce problème… .. Ce n’est pas la commande en chaîne qui était le problème, mais je l’avais eu auparavant.

Le problème était que le serveur n'accepte que les connexions de socket TLS1.2 . La connexion de socket par défaut d'Android 19 et inférieure est TLS1 SSLSocket Docs

Avec l’aide de Activer TLS 1.2 dans Android 4.4 j’ai réussi à le faire fonctionner. La description de la question a fonctionné pour moi. Mais s'il vous plaît assurez-vous que vous avez le code de réponse dans votre application

0
Lawgrin Foul

Je supprime tout le personnel du registre de régimes et le «Aucune erreur de certification entre homologues» est résolu.

c'est à dire. 

Je retire ce code du mien

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

peut-être que vous pouvez essayer de les retirer du vôtre.

0
Krit

J'ai essayé de résoudre ce problème à partir du code Android en ajoutant une règle "accepter tout le certificat". Mais tous les efforts du côté Android ne valaient rien . Enfin, le fait de créer un CNAME dans une entrée de bureau d'enregistrement garantissant que toutes les demandes soient adressées à la même adresse IP a résolu le problème

0
Mridul Shrivastava

Assurez-vous que vous utilisez HttpsURLConnection au lieu de HttpURLConnection.

0
Ajji

En fait, j'essaie actuellement de diagnostiquer cela moi-même, et il semble que le problème soit que le serveur est en panne ou que la connexion a expiré.

0
StackOverflowed