SSLHandshakeException: échec de Handshake sur Android N / 7.0

je travaille sur une application pour laquelle les utilisateurs (power)doivent configurer leur propre serveur (i.e. nginx) pour exécuter l'application backend. Le domaine correspondant doit être configuré dans l'application pour pouvoir se connecter. J'ai été tester principalement sur mon propre téléphone (sony z3c) et a commencé à développer pour 5.1. Plus tard, j'ai reçu une mise à jour 6.0, mais toujours maintenu un travail 5.1 à l'intérieur de l'émulateur. Il n'y a pas si longtemps, j'ai commencé à travailler sur un AVD avec une image pour 7.0 et à ma surprise il ne sera pas connectez-vous à mon serveur, me disant que la poignée de main ssl a échoué. Ma configuration nginx est assez stricte, mais elle fonctionne pour les versions 5.1 et 6.0, donc .... ?!

voici ce que je sais:

  • j'utilise v24 pour les libs de support, c'est-à-dire que mon compileSdkVersion est 24.
  • j'utilise Volley v1.0.0 .
  • j'ai essayé le TLSSocketFactory , mais ça ne change rien. Cela semble être utilisé la plupart du temps pour empêcher L'utilisation de SSL3 pour les anciennes versions SDK de toute façon.
  • j'ai essayé d'augmenter le timeout , mais ça ne change rien.
  • j'ai essayé D'utiliser HttpURLConnection directement, mais cela ne change rien en dehors de la trace de la pile (c'est sans les références de volley, mais identique dans les autres cas).

fait par une simple file d'attente de requêtes, instanciée avec Volley.newRequestQueue(context) .

C'est ce que je vois dans android studio:

W/System.err: com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: Connection closed by peer
W/System.err:     at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:151)
W/System.err:     at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:112)
W/System.err: Caused by: javax.net.ssl.SSLHandshakeException: Connection closed by peer
W/System.err:     at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
W/System.err:     at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357)
W/System.err:     at com.android.okhttp.Connection.connectTls(Connection.java:235)
W/System.err:     at com.android.okhttp.Connection.connectSocket(Connection.java:199)
W/System.err:     at com.android.okhttp.Connection.connect(Connection.java:172)
W/System.err:     at com.android.okhttp.Connection.connectAndSetOwner(Connection.java:367)
W/System.err:     at com.android.okhttp.OkHttpClient.connectAndSetOwner(OkHttpClient.java:130)
W/System.err:     at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:329)
W/System.err:     at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:246)
W/System.err:     at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:457)
W/System.err:     at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:126)
W/System.err:     at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:257)
W/System.err:     at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getOutputStream(DelegatingHttpsURLConnection.java:218)
W/System.err:     at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java)
W/System.err:     at com.android.volley.toolbox.HurlStack.addBodyIfExists(HurlStack.java:264)
W/System.err:     at com.android.volley.toolbox.HurlStack.setConnectionParametersForRequest(HurlStack.java:234)
W/System.err:     at com.android.volley.toolbox.HurlStack.performRequest(HurlStack.java:107)
W/System.err:     at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:96)
W/System.err:   ... 1 more
W/System.err:   Suppressed: javax.net.ssl.SSLHandshakeException: Handshake failed
W/System.err:     at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:429)
W/System.err:       ... 17 more
W/System.err:   Caused by: javax.net.ssl.SSLProtocolException: SSL handshake terminated: ssl=0x7ffef3748040: Failure in SSL library, usually a protocol error
W/System.err: error:10000410:SSL routines:OPENSSL_internal:SSLV3_ALERT_HANDSHAKE_FAILURE (external/boringssl/src/ssl/s3_pkt.c:610 0x7ffeda1d2240:0x00000001)
W/System.err: error:1000009a:SSL routines:OPENSSL_internal:HANDSHAKE_FAILURE_ON_CLIENT_HELLO (external/boringssl/src/ssl/s3_clnt.c:764 0x7ffee9d2b70a:0x00000000)
W/System.err:     at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
W/System.err:     at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357)
W/System.err:       ... 17 more

Puisqu'il est écrit SSLV3_ALERT_HANDSHAKE_FAILURE Je ne peux que supposer qu'il essaie de se connecter en utilisant SSLv3 et échoue, mais cela n'a aucun sens pour moi. C'est peut-être un problème de chiffrement, mais comment savoir ce qu'il essaie d'utiliser ? Je préfère ne pas activer un chiffrement sur le serveur, faire une tentative de connexion et répéter.

mon site nginx utilise un certificat let's encrypt et a la configuration suivante:

ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/ssl/certs/lets-encrypt-x1-cross-signed.pem;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:!aNULL;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_ecdh_curve secp384r1;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1.2;

pour tester ces chiffrements j'ai un script et il confirme ces chiffrements (exécuter sur un VPS wheezy en dehors du réseau du serveur):

Testing ECDHE-RSA-AES256-GCM-SHA384...YES
Testing ECDHE-ECDSA-AES256-GCM-SHA384...NO (sslv3 alert handshake failure)
Testing ECDHE-RSA-AES256-SHA384...NO (sslv3 alert handshake failure)
Testing ECDHE-ECDSA-AES256-SHA384...NO (sslv3 alert handshake failure)
Testing ECDHE-RSA-AES256-SHA...NO (sslv3 alert handshake failure)
Testing ECDHE-ECDSA-AES256-SHA...NO (sslv3 alert handshake failure)
Testing SRP-DSS-AES-256-CBC-SHA...NO (sslv3 alert handshake failure)
Testing SRP-RSA-AES-256-CBC-SHA...NO (sslv3 alert handshake failure)
Testing DHE-DSS-AES256-GCM-SHA384...NO (sslv3 alert handshake failure)
Testing DHE-RSA-AES256-GCM-SHA384...NO (sslv3 alert handshake failure)
Testing DHE-RSA-AES256-SHA256...NO (sslv3 alert handshake failure)
Testing DHE-DSS-AES256-SHA256...NO (sslv3 alert handshake failure)
Testing DHE-RSA-AES256-SHA...NO (sslv3 alert handshake failure)
Testing DHE-DSS-AES256-SHA...NO (sslv3 alert handshake failure)
Testing DHE-RSA-CAMELLIA256-SHA...NO (sslv3 alert handshake failure)
Testing DHE-DSS-CAMELLIA256-SHA...NO (sslv3 alert handshake failure)
Testing AECDH-AES256-SHA...NO (sslv3 alert handshake failure)
Testing SRP-AES-256-CBC-SHA...NO (sslv3 alert handshake failure)
Testing ADH-AES256-GCM-SHA384...NO (sslv3 alert handshake failure)
Testing ADH-AES256-SHA256...NO (sslv3 alert handshake failure)
Testing ADH-AES256-SHA...NO (sslv3 alert handshake failure)
Testing ADH-CAMELLIA256-SHA...NO (sslv3 alert handshake failure)
Testing ECDH-RSA-AES256-GCM-SHA384...NO (sslv3 alert handshake failure)
Testing ECDH-ECDSA-AES256-GCM-SHA384...NO (sslv3 alert handshake failure)
Testing ECDH-RSA-AES256-SHA384...NO (sslv3 alert handshake failure)
Testing ECDH-ECDSA-AES256-SHA384...NO (sslv3 alert handshake failure)
Testing ECDH-RSA-AES256-SHA...NO (sslv3 alert handshake failure)
Testing ECDH-ECDSA-AES256-SHA...NO (sslv3 alert handshake failure)
Testing AES256-GCM-SHA384...NO (sslv3 alert handshake failure)
Testing AES256-SHA256...NO (sslv3 alert handshake failure)
Testing AES256-SHA...NO (sslv3 alert handshake failure)
Testing CAMELLIA256-SHA...NO (sslv3 alert handshake failure)
Testing PSK-AES256-CBC-SHA...NO (no ciphers available)
Testing ECDHE-RSA-DES-CBC3-SHA...NO (sslv3 alert handshake failure)
Testing ECDHE-ECDSA-DES-CBC3-SHA...NO (sslv3 alert handshake failure)
Testing SRP-DSS-3DES-EDE-CBC-SHA...NO (sslv3 alert handshake failure)
Testing SRP-RSA-3DES-EDE-CBC-SHA...NO (sslv3 alert handshake failure)
Testing EDH-RSA-DES-CBC3-SHA...NO (sslv3 alert handshake failure)
Testing EDH-DSS-DES-CBC3-SHA...NO (sslv3 alert handshake failure)
Testing AECDH-DES-CBC3-SHA...NO (sslv3 alert handshake failure)
Testing SRP-3DES-EDE-CBC-SHA...NO (sslv3 alert handshake failure)
Testing ADH-DES-CBC3-SHA...NO (sslv3 alert handshake failure)
Testing ECDH-RSA-DES-CBC3-SHA...NO (sslv3 alert handshake failure)
Testing ECDH-ECDSA-DES-CBC3-SHA...NO (sslv3 alert handshake failure)
Testing DES-CBC3-SHA...NO (sslv3 alert handshake failure)
Testing PSK-3DES-EDE-CBC-SHA...NO (no ciphers available)
Testing ECDHE-RSA-AES128-GCM-SHA256...YES
Testing ECDHE-ECDSA-AES128-GCM-SHA256...NO (sslv3 alert handshake failure)
Testing ECDHE-RSA-AES128-SHA256...NO (sslv3 alert handshake failure)
Testing ECDHE-ECDSA-AES128-SHA256...NO (sslv3 alert handshake failure)
Testing ECDHE-RSA-AES128-SHA...NO (sslv3 alert handshake failure)
Testing ECDHE-ECDSA-AES128-SHA...NO (sslv3 alert handshake failure)
Testing SRP-DSS-AES-128-CBC-SHA...NO (sslv3 alert handshake failure)
Testing SRP-RSA-AES-128-CBC-SHA...NO (sslv3 alert handshake failure)
Testing DHE-DSS-AES128-GCM-SHA256...NO (sslv3 alert handshake failure)
Testing DHE-RSA-AES128-GCM-SHA256...NO (sslv3 alert handshake failure)
Testing DHE-RSA-AES128-SHA256...NO (sslv3 alert handshake failure)
Testing DHE-DSS-AES128-SHA256...NO (sslv3 alert handshake failure)
Testing DHE-RSA-AES128-SHA...NO (sslv3 alert handshake failure)
Testing DHE-DSS-AES128-SHA...NO (sslv3 alert handshake failure)
Testing DHE-RSA-SEED-SHA...NO (sslv3 alert handshake failure)
Testing DHE-DSS-SEED-SHA...NO (sslv3 alert handshake failure)
Testing DHE-RSA-CAMELLIA128-SHA...NO (sslv3 alert handshake failure)
Testing DHE-DSS-CAMELLIA128-SHA...NO (sslv3 alert handshake failure)
Testing AECDH-AES128-SHA...NO (sslv3 alert handshake failure)
Testing SRP-AES-128-CBC-SHA...NO (sslv3 alert handshake failure)
Testing ADH-AES128-GCM-SHA256...NO (sslv3 alert handshake failure)
Testing ADH-AES128-SHA256...NO (sslv3 alert handshake failure)
Testing ADH-AES128-SHA...NO (sslv3 alert handshake failure)
Testing ADH-SEED-SHA...NO (sslv3 alert handshake failure)
Testing ADH-CAMELLIA128-SHA...NO (sslv3 alert handshake failure)
Testing ECDH-RSA-AES128-GCM-SHA256...NO (sslv3 alert handshake failure)
Testing ECDH-ECDSA-AES128-GCM-SHA256...NO (sslv3 alert handshake failure)
Testing ECDH-RSA-AES128-SHA256...NO (sslv3 alert handshake failure)
Testing ECDH-ECDSA-AES128-SHA256...NO (sslv3 alert handshake failure)
Testing ECDH-RSA-AES128-SHA...NO (sslv3 alert handshake failure)
Testing ECDH-ECDSA-AES128-SHA...NO (sslv3 alert handshake failure)
Testing AES128-GCM-SHA256...NO (sslv3 alert handshake failure)
Testing AES128-SHA256...NO (sslv3 alert handshake failure)
Testing AES128-SHA...NO (sslv3 alert handshake failure)
Testing SEED-SHA...NO (sslv3 alert handshake failure)
Testing CAMELLIA128-SHA...NO (sslv3 alert handshake failure)
Testing PSK-AES128-CBC-SHA...NO (no ciphers available)
Testing ECDHE-RSA-RC4-SHA...NO (sslv3 alert handshake failure)
Testing ECDHE-ECDSA-RC4-SHA...NO (sslv3 alert handshake failure)
Testing AECDH-RC4-SHA...NO (sslv3 alert handshake failure)
Testing ADH-RC4-MD5...NO (sslv3 alert handshake failure)
Testing ECDH-RSA-RC4-SHA...NO (sslv3 alert handshake failure)
Testing ECDH-ECDSA-RC4-SHA...NO (sslv3 alert handshake failure)
Testing RC4-SHA...NO (sslv3 alert handshake failure)
Testing RC4-MD5...NO (sslv3 alert handshake failure)
Testing PSK-RC4-SHA...NO (no ciphers available)
Testing EDH-RSA-DES-CBC-SHA...NO (sslv3 alert handshake failure)
Testing EDH-DSS-DES-CBC-SHA...NO (sslv3 alert handshake failure)
Testing ADH-DES-CBC-SHA...NO (sslv3 alert handshake failure)
Testing DES-CBC-SHA...NO (sslv3 alert handshake failure)
Testing EXP-EDH-RSA-DES-CBC-SHA...NO (sslv3 alert handshake failure)
Testing EXP-EDH-DSS-DES-CBC-SHA...NO (sslv3 alert handshake failure)
Testing EXP-ADH-DES-CBC-SHA...NO (sslv3 alert handshake failure)
Testing EXP-DES-CBC-SHA...NO (sslv3 alert handshake failure)
Testing EXP-RC2-CBC-MD5...NO (sslv3 alert handshake failure)
Testing EXP-ADH-RC4-MD5...NO (sslv3 alert handshake failure)
Testing EXP-RC4-MD5...NO (sslv3 alert handshake failure)
Testing ECDHE-RSA-NULL-SHA...NO (sslv3 alert handshake failure)
Testing ECDHE-ECDSA-NULL-SHA...NO (sslv3 alert handshake failure)
Testing AECDH-NULL-SHA...NO (sslv3 alert handshake failure)
Testing ECDH-RSA-NULL-SHA...NO (sslv3 alert handshake failure)
Testing ECDH-ECDSA-NULL-SHA...NO (sslv3 alert handshake failure)
Testing NULL-SHA256...NO (sslv3 alert handshake failure)
Testing NULL-SHA...NO (sslv3 alert handshake failure)
Testing NULL-MD5...NO (sslv3 alert handshake failure

I can ouvrez l'url du serveur dans le navigateur de l'émulateur et obtenez une réponse JSON parfaite pour que je sache que le système lui-même est capable.

alors la question est, pourquoi je ne peux pas me connecter sur Android 7 ?

mise à Jour :

j'ai regardé un paquet capturé en utilisant tcpdump et wireshark et les chiffreurs activés sont dans le ClientHello, donc ça ne devrait pas être un problème.

Cipher Suites (18 suites)

Cipher Suite: Unknown (0xcca9)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)
Cipher Suite: Unknown (0xcca8)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
Cipher Suite: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x009e)
Cipher Suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x009f)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x0033)
Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x0039)
Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c)
Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d)
Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)

comme vous pouvez voir 0xc02f et 0xc030 match, mais le prochain TLSv1.2 paquets disent: Alert (21), Handshake Failure (40) .

Update 2 :

ce sont les courbes D'Android 5.1 dans le ClientHello:

Elliptic curves (25 curves)

Elliptic curve: sect571r1 (0x000e)
Elliptic curve: sect571k1 (0x000d)
Elliptic curve: secp521r1 (0x0019)
Elliptic curve: sect409k1 (0x000b)
Elliptic curve: sect409r1 (0x000c)
Elliptic curve: secp384r1 (0x0018)
Elliptic curve: sect283k1 (0x0009)
Elliptic curve: sect283r1 (0x000a)
Elliptic curve: secp256k1 (0x0016)
Elliptic curve: secp256r1 (0x0017)
Elliptic curve: sect239k1 (0x0008)
Elliptic curve: sect233k1 (0x0006)
Elliptic curve: sect233r1 (0x0007)
Elliptic curve: secp224k1 (0x0014)
Elliptic curve: secp224r1 (0x0015)
Elliptic curve: sect193r1 (0x0004)
Elliptic curve: sect193r2 (0x0005)
Elliptic curve: secp192k1 (0x0012)
Elliptic curve: secp192r1 (0x0013)
Elliptic curve: sect163k1 (0x0001)
Elliptic curve: sect163r1 (0x0002)
Elliptic curve: sect163r2 (0x0003)
Elliptic curve: secp160k1 (0x000f)
Elliptic curve: secp160r1 (0x0010)
Elliptic curve: secp160r2 (0x0011)

dans le ServerHello secp384r1 (0x0018) est retourné.

et ça vient D'Android 7:

Elliptic curves (1 curve)

Elliptic curve: secp256r1 (0x0017)

résultant en L'échec de la poignée de main.

changer la configuration de Nginx en supprimant secp384r1 ou en la remplaçant par la valeur par défaut (prime256v1) permet de travail. Donc je suppose que la question demeure: est-ce que je peux ajouter des courbes elliptiques ?

les données saisies sont les mêmes lorsque vous utilisez l'émulateur que lorsque vous utilisez un appareil Android 7.0 (General Mobile 4G).

Update 3 :

petite mise à jour, mais à noter: Je l'ai fait fonctionner dans L'émulateur en utilisant Android 7.1.1 (!). Il montre les données suivantes (encore une fois, saisi en utilisant tcpdump et vu en utilisant wireshark)):

Elliptic curves (3 curves)

Elliptic curve: secp256r1 (0x0017)
Elliptic curve: secp384r1 (0x0018)
Elliptic curve: secp512r1 (0x0019)

il montre les mêmes 18 Suites cryptées.

44
demandé sur Community 2016-08-25 00:39:27

5 réponses

il s'agit d'une régression connue dans Android 7.0, reconnu par Google et corrigé quelque temps avant la sortie de Android 7.1.1. voici le rapport de bug: https://code.google.com/p/android/issues/detail?id=224438 .

pour être clair, le bug ici est que 7.0 ne supporte QU'une courbe elliptique: prime256v1 alias secp256r1 alias NIST P-256, comme Cornelis le souligne dans la question. Donc, si vos utilisateurs sont confrontés à ce problème, ces sont les solutions de rechange disponibles pour vous (ignorant le fait que vos utilisateurs devraient idéalement juste mettre à jour à Android 7.1.1):

  • configurez votre serveur pour utiliser la courbe elliptique prime256v1 . Par exemple, dans Nginx 1.10 vous faites cela en paramétrant ssl_ecdh_curve prime256v1; .

  • si cela ne fonctionne pas, utilisez des suites de chiffrement plus anciennes qui ne reposent pas sur la cryptographie à courbe elliptique (par exemple, DHE-RSA-AES256-GCM-SHA384 ) (assurez-vous de comprendre ce que vous faites ici en termes de sécurité des données)

NOTE: je suis pas un expert en cryptographie à courbe elliptique, assurez-vous de faire vos propres recherches sur les implications de sécurité de mes suggestions. Voici quelques autres liens que j'ai mentionnés en écrivant cette réponse:

41
répondu Vicky Chijwani 2017-02-06 12:51:02

j'ai eu le problème avec un certificat auto signé et le problème était dans le chiffre qui n'a pas été accepté par Android 7.0

j'ai couru: openssl s_client -showcerts -connect <domain>:<port>

dans le résultat j'ai trouvé:

Protocol : TLSv1
Cipher   : DHE-RSA-AES256-SHA

j'ai cherché L'équivalent Android du Cipher et je l'ai ajouté à mon Restadapter Retrofit:

ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
            .tlsVersions(TlsVersion.TLS_1_2)
            .cipherSuites(

CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA)
            .build();

clientBuilder.connectionSpecs(Collections.singletonList(spec));

D'ici chaque connexion avec le bon épinglage de certificat ou un bon certificat mais avec le "mauvais" cryptage selon Android 7.0 a été accepté.

en regardant en arrière à cette réponse un an plus tard, je dois admettre que je suis toujours heureux je l'ai posté, d'autre part, si vous êtes en mesure de changer le certificat à la suite Cypher correcte s'il vous plaît faire ceci toujours plus "déclassement" suites te acceptées dans votre application. Si vous devez travailler avec un certificat auto-signé (par exemple pour intégré) c'est une solution de travail pour vous.

14
répondu Wessel van Waas 2018-06-11 10:03:34

ici, vous travaillez solution pour Volley:

avant de créer file d'attente dans les codes singleton:

public class VolleyServiceSingleton {

    private RequestQueue mRequestQueue;
    private HurlStack mStack;

    private VolleyServiceSingleton(){

        SSLSocketFactoryExtended factory = null;

        try {
            factory = new SSLSocketFactoryExtended();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }


        final SSLSocketFactoryExtended finalFactory = factory;
        mStack = new HurlStack() {
            @Override
            protected HttpURLConnection createConnection(URL url) throws IOException {
                HttpsURLConnection httpsURLConnection = (HttpsURLConnection) super.createConnection(url);
                try {
                    httpsURLConnection.setSSLSocketFactory(finalFactory);
                    httpsURLConnection.setRequestProperty("charset", "utf-8");

                } catch (Exception e) {
                    e.printStackTrace();
                }
                return httpsURLConnection;
            }

        };



        mRequestQueue = Volley.newRequestQueue(YourApplication.getContext(), mStack, -1);    

    }


}

et voici Sslsockefactoryextend:

public class SSLSocketFactoryExtended extends SSLSocketFactory
{
    private SSLContext mSSLContext;
    private String[] mCiphers;
    private String[] mProtocols;


    public SSLSocketFactoryExtended() throws NoSuchAlgorithmException, KeyManagementException
    {
        initSSLSocketFactoryEx(null,null,null);
    }

    public String[] getDefaultCipherSuites()
    {
        return mCiphers;
    }

    public String[] getSupportedCipherSuites()
    {
        return mCiphers;
    }

    public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException
    {
        SSLSocketFactory factory = mSSLContext.getSocketFactory();
        SSLSocket ss = (SSLSocket)factory.createSocket(s, host, port, autoClose);

        ss.setEnabledProtocols(mProtocols);
        ss.setEnabledCipherSuites(mCiphers);

        return ss;
    }

    public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException
    {
        SSLSocketFactory factory = mSSLContext.getSocketFactory();
        SSLSocket ss = (SSLSocket)factory.createSocket(address, port, localAddress, localPort);

        ss.setEnabledProtocols(mProtocols);
        ss.setEnabledCipherSuites(mCiphers);

        return ss;
    }

    public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException
    {
        SSLSocketFactory factory = mSSLContext.getSocketFactory();
        SSLSocket ss = (SSLSocket)factory.createSocket(host, port, localHost, localPort);

        ss.setEnabledProtocols(mProtocols);
        ss.setEnabledCipherSuites(mCiphers);

        return ss;
    }

    public Socket createSocket(InetAddress host, int port) throws IOException
    {
        SSLSocketFactory factory = mSSLContext.getSocketFactory();
        SSLSocket ss = (SSLSocket)factory.createSocket(host, port);

        ss.setEnabledProtocols(mProtocols);
        ss.setEnabledCipherSuites(mCiphers);

        return ss;
    }

    public Socket createSocket(String host, int port) throws IOException
    {
        SSLSocketFactory factory = mSSLContext.getSocketFactory();
        SSLSocket ss = (SSLSocket)factory.createSocket(host, port);

        ss.setEnabledProtocols(mProtocols);
        ss.setEnabledCipherSuites(mCiphers);

        return ss;
    }

    private void initSSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random)
            throws NoSuchAlgorithmException, KeyManagementException
    {
        mSSLContext = SSLContext.getInstance("TLS");
        mSSLContext.init(km, tm, random);

        mProtocols = GetProtocolList();
        mCiphers = GetCipherList();
    }

    protected String[] GetProtocolList()
    {
        String[] protocols = { "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"};
        String[] availableProtocols = null;

        SSLSocket socket = null;

        try
        {
            SSLSocketFactory factory = mSSLContext.getSocketFactory();
            socket = (SSLSocket)factory.createSocket();

            availableProtocols = socket.getSupportedProtocols();
        }
        catch(Exception e)
        {
            return new String[]{ "TLSv1" };
        }
        finally
        {
            if(socket != null)
                try {
                    socket.close();
                } catch (IOException e) {
                }
        }

        List<String> resultList = new ArrayList<String>();
        for(int i = 0; i < protocols.length; i++)
        {
            int idx = Arrays.binarySearch(availableProtocols, protocols[i]);
            if(idx >= 0)
                resultList.add(protocols[i]);
        }

        return resultList.toArray(new String[0]);
    }

    protected String[] GetCipherList()
    {
        List<String> resultList = new ArrayList<String>();
        SSLSocketFactory factory = mSSLContext.getSocketFactory();
        for(String s : factory.getSupportedCipherSuites()){
            Log.e("CipherSuite type = ",s);
            resultList.add(s);
        }
        return resultList.toArray(new String[resultList.size()]);
    }

}

dans ces codes Je simple ajouter tous les chiffres qui sont supportés par l'appareil, pour moi cela fonctionne), peut être aidera quelqu'un) Santé)

p. S. pas besoin d'ajouter le paramètre de configuration du réseau de sécurité dans manifest.

5
répondu Stepan Maksymov 2016-10-23 00:02:18

par défaut, les connexions sécurisées (utilisant des protocoles tels que TLS et HTTPS) de toutes les applications font confiance au système préinstallé CAs, et les applications ciblant Android 6.0 (niveau API 23) et inférieur font également confiance au magasin CA ajouté par l'utilisateur par défaut.

ce qui signifie que sur Android Nougat (7.0), Le jeu pour CAs a complètement changé. Si vous avez votre clé cert, vous pouvez ajouter un fichier de configuration de sécurité réseau( si vous avez votre cert), comme décrit ici: https://developer.android.com/training/articles/security-config.html

ou vous pouvez créer votre propre gestionnaire de confiance, comme décrit ici: https://developer.android.com/training/articles/security-ssl.html#SelfSigned

ou vous pouvez activer les suites de chiffrement que votre serveur exige mais qui ne sont pas activées par défaut sur Android N. Par exemple, voici deux chiffreurs que j'ai dû ajouter dans ma propre application parler à un vieux serveur Windows CE:

    SSLSocket sslsock = (SSLSocket) createSocket();
    List<String> cipherSuitesToEnable = new ArrayList<>();
    cipherSuitesToEnable.add("SSL_RSA_WITH_RC4_128_SHA");
    cipherSuitesToEnable.add("SSL_RSA_WITH_3DES_EDE_CBC_SHA");
    sslsock.setEnabledCipherSuites(cipherSuitesToEnable.toArray(new String[cipherSuitesToEnable.size()]));
2
répondu Igor Ganapolsky 2016-10-05 14:36:28

Idem. Mon serveur Nginx utilise le paramètre sll_ecdh_curve prime384v1. Malheureusement, guy backend ne m'a pas permis de configurer le serveur Nginx en suivant les instructions de Vicky Chijwani à cause des politiques de sécurité du Client. J'ai essayé D'utiliser Valley et la dernière version de la bibliothèque OkHttp, mais cela n'a pas aidé. Pour contourner ce bug, J'ai dû utiliser WebView pour communiquer avec le Service API sur les périphériques Adroid 7.0. Voici ma classe D'Adaptateur. J'espère que quelqu'un va trouver utile.

/**
* Connection to API service using WebView (for Android 7.0 devices)
*
* Created by fishbone on 09.08.17.
*/
@RequiresApi(api = Build.VERSION_CODES.N)
class WebViewHttpsConnection extends ApiConnection {

    private static final long TIMEOUT = 30000;
    private static final String POST_DATA_SCRIPT = "javascript:(function (){" +
            "var xhr = new XMLHttpRequest();\n" +
            "xhr.open(\"POST\", \"%1$s\", true);\n" +
            "xhr.setRequestHeader(\"Content-type\", \"application/json\");\n" +
            "xhr.onreadystatechange = function () {\n" +
            "    if (xhr.readyState === 4) {\n" +
            "        listener.onResult(xhr.status, xhr.responseText);\n" +
            "    }\n" +
            "};\n" +
            "xhr.send('%2$s');\n" +
            "})();";

    WebViewHttpsConnection(Context context) {
        super(context);
    }
    /**
     *  Send data to API Service.
     *
     * @param url URL of API Service
     * @param request JSON Object serialized into String
     * @return API response
     * @throws IOException errors
     */
    @Override
    public String sendData(final URL url, final String request) throws IOException {
        // We should escape backslashes in JSON because JS unescape it back
        final String javaScript = String.format(POST_DATA_SCRIPT, url.toString(),
                request.replace("\", "\\"));
        final RequestResultListener listener = new RequestResultListener();
        // We must use WebView only from 'main' Thread, therefore I using Handler with Application context
        Handler handler = new Handler(getContext().getApplicationContext().getMainLooper());
        handler.post(new Runnable() {

            @SuppressLint({"SetJavaScriptEnabled", "AddJavascriptInterface"}) // JavaScript is only for me and I'll use it only on Android 7.0 devices, so not scary
            @Override
            public void run() {
                // WebView must be created, configured and called from the same Thread
                final WebView webView = new WebView(getContext(), null);
                webView.getSettings().setJavaScriptEnabled(true);
                webView.addJavascriptInterface(listener, "listener");
                webView.setWebViewClient(new WebViewClient() {

                    @Override
                    public void onPageFinished(WebView view, String url) {
                        // As soon as loaded any page from target domain, we call JS-script that will make POST request
                        webView.loadUrl(javaScript);
                    }
                });
                // I cant use postUrl() method because WebView doesn't allow to define 'Content-type' header, but my API service accepts only 'application/json' content type
                // To complete CORS requirements we make any GET request to lets WebView navigate to the target domain, otherwise it will send 'null' as 'Origin' in headers
                webView.loadUrl(url.toString());
            }
        });
        // And further we waiting for response of API service
        try {
            if (!listener.latch.await(TIMEOUT, TimeUnit.MILLISECONDS)) {
                throw new IOException("Timeout connection to server");
            }
        } catch (InterruptedException e) {
            throw new IOException("Connection to server was interrupted");
        }
        if (listener.code != HttpURLConnection.HTTP_OK) {
            throw new HttpRetryException("Server return error code " + listener.code,
                    listener.code);
        }
        if (TextUtils.isEmpty(listener.result)) {
            throw new HttpRetryException("Service return empty response", listener.code);
        }
        return listener.result;
    }
    /**
     * Callback interface for receiving API Service response from JavaScript inside WebView
     */
    private static class RequestResultListener {

        CountDownLatch latch = new CountDownLatch(1);
        String result = null;
        int code;

        @JavascriptInterface
        public void onResult(int code, String result) {
            this.result = result;
            this.code = code;
            latch.countDown();
        }
    }
}
0
répondu Nikolay 2017-08-10 08:10:36