Avant-propos
Récemment, un problème lié à HTTPS doit être résolu, j'ai donc passé du temps à apprendre la plate-forme Android HTTPS, et en même temps, j'ai également lu certains principes de HTTPS.
Principe HTTPS
HTTPS (Hyper Text Transfer Protocol Secure) est un HTTP basé sur SSL / TLS. Le protocole HTTPS est basé sur le protocole HTTP, ajoutant une transmission de poignée de main SSL / TLS et de cryptage de données, qui appartient également au protocole de couche d'application. Par conséquent, le principe d'étude du protocole HTTPS est enfin d'étudier le protocole SSL / TLS.
Effet du protocole SSL / TLS
La communication HTTP sans SSL / TLS n'est pas une communication cryptée.
1. Risque d'écoute: des tiers peuvent se renseigner sur le contenu de la communication.
2. Risque de falsification: un tiers peut modifier le contenu de la notification.
3. Précurses risques: des tiers peuvent prétendre être l'identité des autres pour participer à la communication.
Le protocole SSL / TLS est conçu pour résoudre ces trois risques.
1. Toutes les informations sont cryptées la transmission et le tiers ne peut pas écouter.
2. Il y a un mécanisme de vérification.
3. Équipé d'un certificat d'identification pour empêcher l'identité d'identifier.
Processus de fonctionnement de base
L'idée de base du protocole SSL / TLS est d'utiliser la méthode de cryptage de la clé publique, c'est-à-dire que le client demande d'abord la clé publique au serveur, puis utilise la clé publique pour les informations chiffrées. , il sera décrypté par sa propre clé privée. Mais ici, vous devez comprendre la solution aux deux problèmes.
1. Comment s'assurer que la clé publique n'est pas falsifiée?
Solution: Placez la clé publique dans un certificat numérique. Tant que le certificat est crédible, la clé publique est crédible.
2. Le montant du cryptage des clés publics est trop important, comment réduire la consommation de temps?
Solution: chaque dialogue, le côté client et serveur génère une "clé de session" (clé de session) pour chiffrer les informations. Parce que la "clé de dialogue" est un chiffrement symétrique, la vitesse de fonctionnement est très rapide et la clé publique du serveur n'est utilisée que pour crypter la "clé de dialogue" elle-même, ce qui réduit la consommation temporelle des opérations cryptées.
Par conséquent, le processus de base du protocole SSL / TLS est comme ceci:
1. Le client est demandé au serveur et vérifie la clé publique.
2. Les deux parties négocient et génèrent la "clé de dialogue".
3. Les deux parties utilisent la "clé de dialogue" pour effectuer une communication cryptée.
Les deux premiers tissus dans le processus ci-dessus sont également appelés "stade de poignée de main".
Le processus détaillé de l'étape de la poignée de main
"Stage Handhake" implique quatre communications.
Le client a publié une demande (ClientHello)
Tout d'abord, le client (généralement le navigateur) envoie une demande de communication chiffrée au serveur, qui s'appelle ClientHello Request. Dans cette étape, le client fournit principalement les informations suivantes au serveur:
1. Version du protocole pris en charge, comme la version TLS 1.0
2. Le nombre aléatoire généré par un client est plus tard utilisé pour générer la "clé de dialogue".
3. Méthodes de chiffrement soutenables, telles que le cryptage des clés publics RSA.
4. Méthode de compression de support.
Il convient de noter que les informations envoyées par le client n'incluent pas le nom de domaine du serveur. En d'autres termes, le serveur théorique ne peut contenir qu'un seul site Web, sinon il ne sera pas clair pour un certificat numérique dont le site Web fournit le client. C'est pourquoi un serveur n'a généralement qu'un seul certificat numérique.
Serveur
Une fois que le serveur a reçu une demande client, il a répondu au client, appelé ServerHello. La réponse du serveur comprend le contenu suivant:
1. Confirmez la version du protocole de communication chiffré, tel que la version TLS 1.0. Si le navigateur est incompatible avec la version prise en charge par le serveur, le serveur arrête la communication cryptée.
2. Le nombre aléatoire généré par un serveur est utilisé plus tard pour générer la "clé de dialogue".
3. Confirmez la méthode de chiffrement utilisée, telle que le cryptage des clés publics RSA.
4. Certificat de serveur.
En plus des informations ci-dessus, si le serveur doit confirmer l'identité du client, il comprendra une autre demande, demandant au client de fournir un "certificat client". Par exemple, les institutions financières permettent souvent aux clients certifiés de se connecter à leurs propres réseaux et fourniront la clé USB aux clients formels, qui contient un certificat client.
Une fois que le client a répondu au client a reçu la réponse du serveur, le certificat de serveur a d'abord vérifié le serveur. Si le certificat n'est pas délivré par l'institution de confiance, ou si le nom de domaine du certificat est incompatible avec le nom de domaine réel, ou si le certificat a expiré, il montrera un avertissement aux visiteurs, et s'il faut continuer à communiquer à partir du choix .
S'il n'y a pas de problème avec le certificat, le client retirera la clé publique du certificat. Envoyez ensuite les trois messages suivants au serveur.
1. Un nombre aléatoire. Le nombre aléatoire du serveur est crypté pour éviter d'être appuyé.
2. Le code modifie la notification, indiquant que les informations suivantes seront envoyées avec les méthodes de chiffrement et les clés convenues par les deux parties.
3. La poignée de main du client termine l'avis, indiquant que l'étape de la poignée du client s'est terminée. Cet élément est généralement la valeur de hachage de tous les contenus de la vérification précédemment envoyée au serveur.
Le premier nombre aléatoire ci-dessus est le troisième nombre aléatoire qui apparaît dans toute la étape de la poignée de main, également connu sous le nom de "clé de pré-master". Avec lui, le client et le serveur ont trois nombres aléatoires en même temps, puis les deux parties utilisent la méthode de cryptage convenue à l'avance pour générer la même "clé de session" utilisée dans la session.
Une fois que le serveur de réponse final du serveur a reçu la troisième touche de pré-master aléatoire du client, calcule la "clé de session" utilisée dans la session générée. Envoyez ensuite les informations suivantes au client.
1. Le code modifie la notification, indiquant que les informations suivantes seront envoyées avec les méthodes de chiffrement et les clés convenues par les deux parties.
2. La poignée de main du serveur met fin à l'avis, indiquant que l'étape de la poignée de main du serveur est terminée. Cet élément est également la valeur de hachage de tous les contenus précédents, qui est utilisé pour la vérification du client.
Fin de poignée
À ce stade, toute la phase de poignée de main est terminée. Ensuite, le client et le serveur entrent la communication chiffrée, qui utilise un protocole HTTP ordinaire, mais utilise le contenu de cryptage "clé de session".
Le serveur a construit le site virtuel HTTPS basé sur Nginx
L'article précédent introduit en détail comment générer des certificats SSL côté serveur et créer un serveur HTTPS basé sur Nginx, lien: Nginx construit un serveur HTTPS
Implémentation Android de la communication HTTPS
Pour diverses raisons, utilisez la classe HTTPCLICENT pour expliquer comment Android établit une connexion HTTPS. La démo de code est la suivante.
Mainactivity.java
package com.example.Photocrop; client.httpclient; Importation Android.util.log; Super.onCreate (SavedInstancEstate); ) {runHTTPSConnecti sur ();}}); httpstask.getStatus () == StatShed) {httpstSt Ask = new CreateHtPSConnTask (); sbuffer = New StringBuffer (); @Override Protected Void Doinbackground (void ... Params) { Httpurirequest request = new httppost (https_example_url); httpclient httpclient = httputill.gethttpsclient (); Try {httpresponse httpresponse = httpclient.execute (request); if (httpResponse! = null) {statustline statusLe = httpResponse.getStatusline (); (Http Response.getEntity (). GetContent (), "UTF-8"); String Line = Null; (Exception e) {log.e (https ", e.getMessage ());} enfin {si ) Ot .toString ());}}}}
Httputils.java
package com.example.photocrop; Conn.scheme.scheme; .apache.Params.basichtpparams; Newtppara MS (); eregistry (); etfactory (), 80) ); ) {Basichtpparams Params = new Basichttpparams (); .greger (nouveau schéma ( "HTTP", PlainsocketSocketSocketFactory (), 80); Httpclient getSpect (contexte de contexte) {BasichTtpparams params = new Basichtpparams (); S, vrai); SchemeRegstry () ;; }}
activité_main.xml
<linearlayout xmlns: android = "http://schemas.android.com/apk/res/android" xmlns: tool "Match_pareat" Android: orientation = "vertical"> <bouton Android: id = "@ + id / create_button" Android: Layout_ "Match_ Parent" ID: Layout_height = "wrap_content" Android: text = "string / hello_world" Android: TextSize = "16sp" /> <textView Android: id = "@ + id / content_textView" Android: Layout_Width = "Match_parent" Android: Layout_Height = "WRA P_Content" Android: Gravity = "Center" Android: TextSize = "16SP" / /> </ Linearlayout>
Android utilise le defaulthTTPClient pour établir une connexion HTTPS.
Schreg.register (nouveau schéma ("https", sslsocketfactory.getSocketFactory (), 443));
Rejoignez la prise en charge de HTTPS, vous pouvez établir efficacement la connexion HTTPS, telle que "https://www.google.com.hk", mais il n'est pas possible de vous accéder en fonction du serveur HTTPS construit par Nginx, car il l'est non utilisé par le système à utiliser par le système.
Utilisez un certificat personnalisé et ignorez la méthode de connexion HTTPS vérifiée
La méthode de résolution du certificat n'est pas reconnu par le système est de sauter la vérification du système. Si vous souhaitez sauter la vérification du système, vous ne pouvez plus utiliser le sketfactory SSL standard du système. Ensuite, afin de sauter la vérification dans ce socketfactory SSL personnalisé, vous devez également personnaliser un TrustManager, qui ignore toutes les vérifications, c'est-à-dire TrustAll.
package com.example.Photocrop; Importation java.security.nosuchalgorithMexception; .xl.x509TrustManager; GementException, KeyStorexception, UncoverableKException {super (TrustStore); Nouveau x509TrustManager () {@Override public x509Certified [] geta CceptedSSSUers () {return null;} @Override public void CheckServerTruted (x509Certiftified [] chaîne, String AuthType) lance {} @ override public Void CheckClitTruted (x509CERI ) Lance Certificatexception {}}; (Socket socket, Port de chaîne, booléen autoclose), inconnuehostException {return sslContext.getSocketFactory (). ));
Dans le même temps, vous devez modifier la méthode de registre du defaultTTPClient pour passer à SSLSocket que vous avez construit:
Public statique httpclient getCustomClient () {basichtpparams params = new BasichTtpparams (); inscrire (nouveau schéma ("HTTP ", plainsocketfactory.getsocketfactory (), 80)); schreg.register (" httpsoc "kectory.getsocketfactory (), 443)); clientConnectionManager Connmgr = new ThreadSaFecLentConnManager (params, schreg); return newtTpClient (ConnemMgr, Params);}
De cette façon, vous pouvez accéder avec succès au site virtuel HTTPS basé sur NGINX.
défaut:
Cependant, bien que cette solution utilise HTTPS, le contenu de communication du client et du serveur est chiffré, le programme de reniflement ne peut pas obtenir le contenu de la transmission, mais il ne peut pas résister à "Middleman Attack". Par exemple, configurez un DNS dans le réseau intérieur, analysez le nom de domaine du serveur cible sur une adresse locale, puis utilisez un serveur intermédiaire en tant qu'agent sur cette adresse. certificats. De cette façon, tout le contenu de la communication passera cet agent et le client ne percevra pas, ce qui est causé par le certificat de clé publique du serveur non vérifiable du client.
Utilisez un certificat personnalisé pour établir une connexion HTTPS
Afin d'empêcher «l'attaque intermédiaire» qui peut être causée par le schéma ci-dessus, nous pouvons télécharger le certificat de clé publique du serveur, puis compiler le certificat de clé publique sur l'application Android pour vérifier le certificat par lui-même.
Générer des clés
Pour vérifier le certificat personnalisé, nous devons d'abord compiler le certificat à l'application. Le certificat fait ici référence à la clé publique du serveur cible, qui peut être obtenu à partir du fichier .crt ou du fichier .pem configuré par le serveur Web. En même temps, vous devez configurer Bouundcastle.
Keytool -ImportCert -v -trustcacerts -alias Exemple -File www.example.com.crt -Keystore example.bks -StoreType Bks -ProviderClass Rovider.boundcastleprovider -ProviderPath / Home / Wzy / Downloads / Java / JDK1 .7.0_60 / Jre / lib / ext / bcprov-jdk16-145.jar-storepass pw123456
Après l'exécution, le contenu du certificat sera affiché et vous invite à confirmer si vous pouvez entrer Y Entrée.
Une fois la production du fichier de clés réussi, mettez-la dans le répertoire Res / brut de l'application APP.
L'utilisation de Keystore personnalisée pour implémenter des idées de connexion est similaire à Trushall.
package com.example.Photocrop; Java.Security.unrecoverableyException; Magasin);} Public statique SSLSocketFactory Ext. ;} Catch (exception e) {e.printStackTrace (); entrée = null;}}}}}}}}}}}}}
Dans le même temps, vous devez modifier la méthode de registre du defaultTTPClient pour passer à SSLSocket que vous avez construit:
Public statique httpclient getSpecilKeyStoreClient (contexte de contexte) {BasichTTPParams params = new BasichTTPParams (); Schémas schémas schreg = nouveau schéma ( )); Params);}}