Maison  >  Article  >  Tutoriel système  >  Analyser les principes du HTTPS et son utilisation sous Android

Analyser les principes du HTTPS et son utilisation sous Android

王林
王林avant
2024-02-23 08:00:211067parcourir
1. Lacunes du protocole HTTP

Lorsque HTTP1.x transmet des données, tout le contenu transmis est en texte clair. Ni le client ni le serveur ne peuvent vérifier l'identité de l'autre partie :

  • La communication utilise du texte clair (non crypté) et le contenu peut être écouté ;
  • Si vous ne vérifiez pas l'identité de la partie communicante, vous risquez de rencontrer un déguisement ;
  • L'intégrité du message ne peut être prouvée, il se peut donc qu'il ait été falsifié ;

En fait, ces problèmes se produisent non seulement en HTTP, mais également dans d'autres protocoles non chiffrés.

(1) Les communications utilisant du texte clair peuvent être écoutées

Selon le mécanisme de fonctionnement de la suite de protocoles TCP/IP, il existe un risque que le contenu de la communication soit écouté n'importe où sur Internet. Le protocole HTTP lui-même n'a pas de fonction de cryptage et toutes les données transmises sont du texte brut. Même si la communication a été cryptée, le contenu de la communication sera consulté, ce qui est le même que la communication non cryptée. Cela signifie simplement que si la communication est cryptée, il peut être impossible de déchiffrer la signification des informations du message, mais le message crypté lui-même sera toujours visible.

(2) Le défaut de vérification de l'identité de la partie communicante peut conduire à un déguisement

Pendant la communication selon le protocole HTTP, puisqu'il n'y a aucune étape de traitement pour confirmer la partie communicante, n'importe qui peut lancer une demande. De plus, tant que le serveur reçoit la requête, il renvoie une réponse quelle que soit l'identité de l'autre partie. Par conséquent, si la partie communication n'est pas confirmée, il existe les dangers cachés suivants :

  • Il est impossible de déterminer si le serveur web auquel la requête est envoyée est celui qui renvoie la réponse selon la véritable intention. Il s'agit peut-être d'un serveur Web déguisé ;
  • Il n'existe aucun moyen de déterminer si le client auquel la réponse est renvoyée est celui qui a reçu la réponse comme prévu. Il s'agit peut-être d'un client déguisé ;
  • Il est impossible de déterminer si l'autre partie avec laquelle vous communiquez dispose de droits d'accès. Étant donné que certains serveurs Web stockent des informations importantes, ils souhaitent uniquement accorder des autorisations de communication à des utilisateurs spécifiques ;
  • Il est impossible de déterminer d'où vient la demande et qui l'a formulée ;
  • Même les demandes dénuées de sens seront acceptées comme ordonnées, incapables d'empêcher les attaques DoS en cas de demandes massives ;

(3) L'intégrité du message ne peut être prouvée et il peut avoir été falsifié

La soi-disant exhaustivité fait référence à l'exactitude des informations. Le fait de ne pas démontrer leur exhaustivité signifie généralement qu’il est impossible de juger si les informations sont exactes. Le protocole HTTP ne peut pas prouver l'intégrité des messages de communication. Pendant la période qui suit l'envoi de la demande ou de la réponse jusqu'à ce que l'autre partie la reçoive, il n'y a aucun moyen de savoir même si le contenu de la demande ou de la réponse a été falsifié.

Par exemple, lors du téléchargement de contenu depuis un site Web, il est impossible de déterminer si les fichiers téléchargés par le client et les fichiers stockés sur le serveur sont cohérents. Le contenu du fichier peut avoir été altéré avec d'autres contenus pendant la transmission. Même si le contenu a réellement changé, le client comme le destinataire n’en a pas conscience. Ainsi, une attaque dans laquelle la demande ou la réponse est interceptée par l'attaquant et falsifié le contenu pendant la transmission est appelée attaque Man-in-the-Middle (MITM).

分析 HTTPS 原理以及在 Android 中的使用

(4) Plusieurs caractéristiques que devrait avoir une version HTTP sécurisée

En raison des problèmes ci-dessus, une technologie de sécurité HTTP pouvant fournir les fonctions suivantes est nécessaire :

(1) Authentification du serveur (les clients savent qu'ils parlent à un vrai serveur et non à un faux serveur) ;

(2) Authentification du client (les serveurs savent qu'ils parlent à un vrai client et non à un faux client) ;

(3) Intégrité (les données sur le client et le serveur ne seront pas modifiées) ;

(4) Cryptage (la conversation entre le client et le serveur est privée, pas besoin de craindre d'être écouté) ;

(5) Efficacité (un algorithme qui s'exécute suffisamment vite pour être utilisé par les clients et les serveurs bas de gamme) ;

(6) Universalité (essentiellement tous les clients et serveurs prennent en charge ces protocoles) ;

2.Technologies clés du HTTPS

Dans le contexte d'une telle demande, la technologie HTTPS est née. Les principales fonctions du protocole HTTPS reposent essentiellement sur le protocole TLS/SSL, qui fournit des fonctions d'authentification, de cryptage des informations et de vérification de l'intégrité, ce qui peut résoudre les problèmes de sécurité du HTTP. Cette section se concentrera sur plusieurs points techniques clés du protocole HTTPS.

分析 HTTPS 原理以及在 Android 中的使用

(1) Technologie de cryptage

Les algorithmes de chiffrement sont généralement divisés en deux types :

Cryptage symétrique : la clé de cryptage et de déchiffrement est la même. Représenté par l'algorithme DES ;

Cryptage asymétrique : Les clés de cryptage et de déchiffrement sont différentes. Représenté par l'algorithme RSA ;

Le cryptage symétrique est très puissant et ne peut généralement pas être déchiffré. Cependant, un gros problème est que la clé ne peut pas être générée et stockée en toute sécurité si chaque session entre le client et le serveur utilise une clé fixe et identique pour le cryptage et le déchiffrement. présenter de grands risques pour la sécurité.

Avant l'émergence des algorithmes d'échange de clés asymétriques, un gros problème avec le chiffrement symétrique était de ne pas savoir comment générer et stocker les clés en toute sécurité. Le processus d'échange asymétrique de clés vise principalement à résoudre ce problème et à rendre la génération et l'utilisation des clés plus sécurisées. Mais c’est aussi le « coupable » qui réduit considérablement les performances et la vitesse HTTPS.

HTTPS utilise un mécanisme de cryptage hybride qui utilise à la fois un cryptage symétrique et un cryptage asymétrique. Il utilise un cryptage asymétrique dans le processus d'échange de clés et utilise un cryptage symétrique dans les étapes ultérieures de communication et d'échange de messages.

(2) Authentification – Certificat prouvant l'exactitude de la clé publique

L'un des plus gros problèmes du cryptage asymétrique est qu'il ne peut pas prouver que la clé publique elle-même est la véritable clé publique. Par exemple, lors de la préparation d'une communication avec un certain serveur à l'aide d'un cryptage à clé publique, comment prouver que la clé publique reçue est la clé publique émise par le serveur initialement attendu. Il se peut que lors de la transmission de la clé publique, la véritable clé publique ait été remplacée par l'attaquant.

Si la fiabilité de la clé publique n'est pas vérifiée, il y aura au moins les deux problèmes suivants : attaque de l'homme du milieu et déni d'information.

分析 HTTPS 原理以及在 Android 中的使用

Afin de résoudre les problèmes ci-dessus, vous pouvez utiliser des certificats de clé publique émis par les autorités de certification de certificats numériques (CA, Certificate Authority) et leurs agences associées.

分析 HTTPS 原理以及在 Android 中的使用

Le processus spécifique d'utilisation de CA est le suivant :

(1) L'opérateur du serveur demande une clé publique à l'autorité de certification des certificats numériques (CA) ;

(2) CA vérifie l'authenticité des informations fournies par le demandeur par des moyens en ligne, hors ligne et autres, par exemple si l'organisation existe, si l'entreprise est légale, si elle est propriétaire du nom de domaine, etc. ;

(3) Si les informations sont approuvées, l'autorité de certification signera numériquement la clé publique appliquée, puis distribuera la clé publique signée, placera la clé publique dans le certificat de clé publique et la liera. Le certificat contient les informations suivantes : la clé publique du demandeur, les informations organisationnelles et personnelles du demandeur, les informations de l'autorité émettrice CA, la durée de validité, le numéro de série du certificat et d'autres informations en texte clair, et contient également une signature ; algorithme de génération de signature : utilisez d'abord le hachage. La fonction de colonne calcule le résumé des informations publiques en clair, puis utilise la clé privée de l'autorité de certification pour chiffrer le résumé des informations, et le texte chiffré est la signature ;

(4) Le client envoie une requête au serveur pendant la phase de négociation HTTPS, demandant au serveur de renvoyer le fichier de certificat ;

(5) Le client lit les informations en clair pertinentes dans le certificat, utilise la même fonction de hachage pour calculer le résumé des informations, puis utilise la clé publique de l'autorité de certification correspondante pour déchiffrer les données de signature et compare le résumé des informations du certificat. S'il est cohérent, il peut confirmer la légitimité du certificat, c'est-à-dire que la clé publique est légitime ;

(6) Le client vérifie ensuite les informations du nom de domaine, la durée de validité et d'autres informations liées au certificat ;

(7) Le client aura des informations de certificat de confiance intégrées (y compris la clé publique). Si l'autorité de certification n'est pas fiable, le certificat correspondant à l'autorité de certification ne sera pas trouvé et le certificat sera jugé illégal.

Faites attention à quelques points au cours de ce processus :

(1) Il n'est pas nécessaire de fournir une clé privée lors de la demande de certificat, garantissant que la clé privée ne peut être maîtrisée que par le serveur pour toujours ;

(2) La validité du certificat dépend toujours de l'algorithme de cryptage asymétrique. Le certificat ajoute principalement des informations sur le serveur et une signature ;

(3) Le certificat correspondant à l'autorité de certification intégrée est appelé certificat racine ; l'émetteur et l'utilisateur sont identiques, et ils signent pour eux-mêmes, ce qu'on appelle un certificat auto-signé

;

(4) Certificat = clé publique + informations sur le demandeur et l'émetteur + signature

 ;
3.Principe du protocole HTTPS

(1) Historique du HTTPS

Introduction à l'historique du protocole HTTPS :

  • (1) La première version du protocole SSL a été développée par Netscape, mais cette version n'a jamais été publiée ;
  • (2) La deuxième version du protocole SSL est sortie en novembre 1994. Le premier déploiement a eu lieu sur le navigateur Netscape Navigator 1.1, sorti en mars 1995 ;
  • (3) SSL 3 a été publié fin 1995. Bien que le nom soit le même que celui de la version précédente du protocole, SSL3 est un protocole entièrement repensé et sa conception est toujours utilisée aujourd'hui.
  • (4) TLS 1.0 est sorti en janvier 1999. Par rapport à SSL 3, les modifications de version ne sont pas majeures ;
  • (5) En avril 2006, la version suivante de TLS 1.1 a été publiée, qui n'a résolu que quelques problèmes de sécurité clés ;
  • (6) En août 2008, TLS1.2 est sorti. Cette version ajoute la prise en charge du cryptage authentifié et supprime essentiellement toutes les primitives de sécurité codées en dur de la description du protocole, ce qui rend le protocole complètement résilient
  •  ;

(2) Mise en œuvre du protocole

Macroscopiquement, TLS est implémenté par le protocole d'enregistrement. Le protocole d'enregistrement est responsable de l'échange de tous les messages de bas niveau via la connexion de transport et peut être configuré pour le chiffrement. Chaque enregistrement TLS commence par un court en-tête. L'en-tête contient le type (ou sous-protocole), la version du protocole et la longueur du contenu de l'enregistrement. Les données du message suivent l'en-tête comme indiqué ci-dessous :

分析 HTTPS 原理以及在 Android 中的使用

La spécification principale TLS définit quatre sous-protocoles principaux :

  • protocole de poignée de main ;
  • changer le protocole de spécification de chiffrement ;
  • protocole de données d'application ;
  • Protocole d'alerte ;

(3) Accord de poignée de main

La poignée de main est la partie la plus sophistiquée du protocole TLS. Au cours de ce processus, les parties communicantes négocient les paramètres de connexion et complètent l'authentification de l'identité. Selon les fonctions utilisées, l'ensemble du processus nécessite généralement l'échange de 6 à 10 messages. Il peut exister de nombreuses variantes du processus d'échange en fonction de la configuration et des extensions de protocole prises en charge. Les trois processus suivants peuvent souvent être observés en cours d'utilisation :

  • (1) Poignée de main complète pour authentifier le serveur (authentification unidirectionnelle, la plus courante) ;
  • (2) Poignée de main qui authentifie à la fois le client et le serveur (authentification bidirectionnelle) ;
  • (3) Brève poignée de main utilisée pour restaurer la session précédente ;

(4) Processus de prise de contact de vérification unidirectionnelle

Cette section prend le processus de connexion de la boîte aux lettres QQ comme exemple pour analyser le processus de prise de contact de vérification unidirectionnelle en capturant les paquets. Un processus complet de prise de contact pour une vérification unidirectionnelle est le suivant :

分析 HTTPS 原理以及在 Android 中的使用

Il se divise principalement en quatre étapes :

  • (1) Échangez les fonctions supportées par chacun et convenez des paramètres de connexion requis ;
  • (2) Vérifiez le certificat présenté ou utilisez d'autres méthodes d'authentification ;
  • (3) Mettez-vous d'accord sur la clé principale partagée qui sera utilisée pour protéger la session ;
  • (4) Vérifiez si le message de poignée de main a été modifié par un tiers ;

Ce processus est analysé en détail ci-dessous.

1.ClientBonjour

Dans le processus de prise de contact, ClientHello est le premier message. Ce message transmet les capacités et les préférences du client au serveur. Contient la version spécifiée de SSL prise en charge par le client et une liste de suites de chiffrement (algorithme de chiffrement utilisé, longueur de clé, etc.).

分析 HTTPS 原理以及在 Android 中的使用

2.ServeurBonjour

Le message

ServerHello transmet les paramètres de connexion sélectionnés par le serveur au client. La structure de ce message est similaire à ClientHello, sauf que chaque champ ne contient qu'une seule option. Le contenu des composants de chiffrement du serveur et la méthode de compression sont tous filtrés des composants de chiffrement client reçus.

分析 HTTPS 原理以及在 Android 中的使用

3.Certificat

Ensuite, le serveur envoie un message de certificat, qui contient le certificat de clé publique. Le serveur doit s'assurer que le certificat qu'il envoie est cohérent avec la suite d'algorithmes sélectionnée. Cependant, le message Certificat est facultatif car tous les packages n'utilisent pas l'authentification et toutes les méthodes d'authentification ne nécessitent pas de certificats.

分析 HTTPS 原理以及在 Android 中的使用

4.ServerKeyExchange

Le but du message ServerKeyExchange est de transporter des données supplémentaires pour l'échange de clés. Le contenu du message différera selon les différentes suites d'algorithmes de négociation. Dans certains scénarios, le serveur n'a pas besoin d'envoyer quoi que ce soit, et dans ces scénarios, il n'est pas nécessaire d'envoyer un message ServerKeyExchange.

分析 HTTPS 原理以及在 Android 中的使用

5.ServeurBonjourDone

Le message

ServerHelloDone indique que le serveur a terminé l'envoi de tous les messages de prise de contact attendus. Après cela, le serveur attend que le client envoie le message.

分析 HTTPS 原理以及在 Android 中的使用

6.ClientKeyExchange

Le message ClientKeyExchange contient toutes les informations fournies par le client pour l'échange de clés. Ce message est affecté par la suite de chiffrement négociée et son contenu varie en fonction des différentes suites de chiffrement négociées.

分析 HTTPS 原理以及在 Android 中的使用

7.ChangeCipherSpec

Le message

ChangeCipherSpec indique que l'expéditeur a obtenu suffisamment d'informations pour générer les paramètres de connexion, a généré une clé de cryptage et va passer en mode cryptage. Le client et le serveur enverront ce message lorsque les conditions seront réunies. Remarque : ChangeCipherSpec n'appartient pas au message de prise de contact. Il s'agit d'un autre protocole avec un seul message, implémenté comme sous-protocole.

分析 HTTPS 原理以及在 Android 中的使用

8.Terminé

Le message terminé signifie que la poignée de main est terminée. Le contenu du message sera crypté afin que les deux parties puissent échanger en toute sécurité les données nécessaires pour vérifier l'intégrité de l'ensemble de la poignée de main. Le client et le serveur enverront ce message lorsque les conditions seront réunies.

(5) Processus de poignée de main de vérification bidirectionnelle

Dans certains scénarios présentant des exigences de sécurité plus élevées, une vérification bidirectionnelle peut s'avérer nécessaire. Le processus complet de vérification bidirectionnelle est le suivant :

分析 HTTPS 原理以及在 Android 中的使用

Vous pouvez voir que par rapport au processus de vérification unidirectionnelle, la vérification bidirectionnelle comporte les deux messages supplémentaires suivants : CertificateRequest et CertificateVerify. Le reste du processus est à peu près le même.

1.Demande de certificat

La demande de certificat est une fonctionnalité facultative spécifiée par TLS et est utilisée par le serveur pour authentifier l'identité du client. Implémenté par le serveur demandant au client d'envoyer un certificat, le serveur doit envoyer un message CertificateRequest immédiatement après ServerKeyExchange.

La structure du message est la suivante :

enum { 
    rsa_sign(1), dss_sign(2), rsa_fixed_dh(3),dss_fixed_dh(4), 
    rsa_ephemeral_dh_RESERVED(5),dss_ephemeral_dh_RESERVED(6), 
    fortezza_dms_RESERVED(20), 
    ecdsa_sign(64), rsa_fixed_ecdh(65), 
    ecdsa_fixed_ecdh(66),  
    (255) 
} ClientCertificateType; 

opaque DistinguishedName<1..2^16-1>;struct { 
    ClientCertificateType certificate_types<1..2^8-1>; 
    SignatureAndHashAlgorithm 
      supported_signature_algorithms<2^16-1>; 
    DistinguishedName certificate_authorities<0..2^16-1>; 
} CertificateRequest;

Vous pouvez éventuellement envoyer une liste des autorités de certification acceptées, représentées par leurs noms distinctifs.

2.CertificateVerify

Lorsque l'authentification du client est requise, le client envoie un message CertificateVerify pour prouver qu'il possède bien la clé privée du certificat client. Ce message n'est envoyé que si le certificat client dispose de capacités de signature. CertificateVerify doit immédiatement suivre ClientKeyExchange. La structure du message est la suivante :

struct {  
Signature handshake_messages_signature;  
} CertificateVerify;

(6) protocole de données d'application

Le protocole de données d'application transporte les messages d'application. Si l'on y pense uniquement du point de vue de TLS, ce sont des tampons de données. La couche d'enregistrement regroupe, défragmente et chiffre ces messages à l'aide des paramètres de sécurité de connexion actuels. Comme le montre la figure ci-dessous, vous pouvez voir que les données transmises ont été cryptées.

分析 HTTPS 原理以及在 Android 中的使用

(7) protocole d'alerte

Le but de l'alarme est d'informer le pair de conditions de communication anormales via un simple mécanisme de notification. Il comporte généralement une exception close_notify, qui est utilisée lorsque la connexion est fermée pour signaler des erreurs. Les alertes sont très simples, avec seulement deux champs :

struct {  
    AlertLevel level;  
    AlertDescription description;  
} Alert;
  • Champ AlertLevel : indique la gravité de l'alerte ;
  • AlertDescription : représente directement le code d'alerte ;
4. Questions fréquemment posées sur l'utilisation de HTTPS dans Android

(1) 服务器证书验证错误

这是最常见的一种问题,通常会抛出如下类型的异常:

分析 HTTPS 原理以及在 Android 中的使用

出现此类错误通常可能由以下的三种原因导致:

  • (1) 颁发服务器证书的CA未知;
  • (2) 服务器证书不是由CA签署的,而是自签署(比较常见);
  • (3) 服务器配置缺少中间 CA;

当服务器的CA不被系统信任时,就会发生 SSLHandshakeException。可能是购买的CA证书比较新,Android系统还未信任,也可能是服务器使用的是自签名证书(这个在测试阶段经常遇到)。

解决此类问题常见的做法是:指定HttpsURLConnection信任特定的CA集合。在本文的第5部分代码实现模块,会详细的讲解如何让Android应用信任自签名证书集合或者跳过证书校验的环节。

(2) 域名验证失败

SSL连接有两个关键环节。首先是验证证书是否来自值得信任的来源,其次确保正在通信的服务器提供正确的证书。如果没有提供,通常会看到类似于下面的错误:

分析 HTTPS 原理以及在 Android 中的使用

出现此类问题的原因通常是由于服务器证书中配置的域名和客户端请求的域名不一致所导致的。

有两种解决方案:

(1) 重新生成服务器的证书,用真实的域名信息;

(2) 自定义HostnameVerifier,在握手期间,如果URL的主机名和服务器的标识主机名不匹配,则验证机制可以回调此接口的实现程序来确定是否应该允许此连接。可以通过自定义HostnameVerifier实现一个白名单的功能。

代码如下:

HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() { 
  @Override 
  public boolean verify(String hostname, SSLSession session) { 
    // 设置接受的域名集合 
    if (hostname.equals(...))  { 
         return true; 
    } 
  } 
}; 

HttpsURLConnection.setDefaultHostnameVerifier(DO_NOT_VERIFY);

(3) 客户端证书验证

SSL支持服务端通过验证客户端的证书来确认客户端的身份。这种技术与TrustManager的特性相似。本文将在第5部分代码实现模块,讲解如何让Android应用支持客户端证书验证的方式。

(4) Android上TLS版本兼容问题

之前在接口联调的过程中,测试那边反馈过一个问题是在Android 4.4以下的系统出现HTTPS请求不成功而在4.4以上的系统上却正常的问题。相应的错误如下:

03-09 09:21:38.427: W/System.err(2496): javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0xb7fa0620: Failure in SSL library, usually a protocol error 

03-09 09:21:38.427: W/System.err(2496): error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:741 0xa90e6990:0x00000000)

按照官方文档的描述,Android系统对SSL协议的版本支持如下:

分析 HTTPS 原理以及在 Android 中的使用

也就是说,按官方的文档显示,在API 16+以上,TLS1.1和TLS1.2是默认开启的。但是实际上在API 20+以上才默认开启,4.4以下的版本是无法使用TLS1.1和TLS 1.2的,这也是Android系统的一个bug。

参照stackoverflow上的一些方式,比较好的一种解决方案如下:

SSLSocketFactory noSSLv3Factory; 
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) { 
    noSSLv3Factory = new TLSSocketFactory(mSSLContext.getSSLSocket().getSocketFactory()); 
} else { 
    noSSLv3Factory = mSSLContext.getSSLSocket().getSocketFactory(); 
}

对于4.4以下的系统,使用自定义的TLSSocketFactory,开启对TLS1.1和TLS1.2的支持,核心代码:

public class TLSSocketFactory extends SSLSocketFactory { 

    private SSLSocketFactory internalSSLSocketFactory; 

    public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException { 
        SSLContext context = SSLContext.getInstance("TLS"); 
        context.init(null, null, null); 
        internalSSLSocketFactory = context.getSocketFactory(); 
    } 

    public TLSSocketFactory(SSLSocketFactory delegate) throws KeyManagementException, NoSuchAlgorithmException { 
        internalSSLSocketFactory = delegate; 
    } 

    ...... 

    @Override 
    public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { 
        return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort)); 
    } 

    // 开启对TLS1.1和TLS1.2的支持 
    private Socket enableTLSOnSocket(Socket socket) { 
        if(socket != null && (socket instanceof SSLSocket)) { 
            ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"}); 
        } 
        return socket; 
    } 
}
5.代码实现

本部分主要基于第四部分提出的Android应用中使用HTTPS遇到的一些常见的问题,给出一个比较系统的解决方案。

(1) 整体结构

不管是使用自签名证书,还是采取客户端身份验证,核心都是创建一个自己的KeyStore,然后使用这个KeyStore创建一个自定义的SSLContext。整体类图如下:

分析 HTTPS 原理以及在 Android 中的使用

类图中的MySSLContext可以应用在HttpURLConnection的方式与服务端连接的过程中:

if (JarConfig.__self_signed_https) { 
    SSLContextByTrustAll mSSLContextByTrustAll = new SSLContextByTrustAll(); 
    MySSLContext mSSLContext = new MySSLContext(mSSLContextByTrustAll); 
   SSLSocketFactory noSSLv3Factory; 
   if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) { 
        noSSLv3Factory = new TLSSocketFactory(mSSLContext.getSSLSocket().getSocketFactory()); 
    } else { 
        noSSLv3Factory = mSSLContext.getSSLSocket().getSocketFactory(); 
    } 

    httpsURLConnection.setSSLSocketFactory(noSSLv3Factory); 
    httpsURLConnection.setHostnameVerifier(MY_DOMAIN_VERIFY); 
}else { 
    httpsURLConnection.setSSLSocketFactory((SSLSocketFactory) SSLSocketFactory.getDefault()); 
    httpsURLConnection.setHostnameVerifier(DO_NOT_VERIFY); 
}

核心是通过httpsURLConnection.setSSLSocketFactory使用自定义的校验逻辑。整体设计上使用策略模式决定采用哪种验证机制:

  • makeContextWithCilentAndServer 单向验证方式(自定义信任的证书集合)
  • makeContextWithServer 双向验证方式(自定义信任的证书集合,并使用客户端证书)
  • makeContextToTrustAll (信任所有的CA证书,不安全,仅供测试阶段使用)

(2) 单向验证并自定义信任的证书集合

在App中,把服务端证书放到资源文件下(通常是asset目录下,因为证书对于每一个用户来说都是相同的,并且也不会经常发生改变),但是也可以放在设备的外部存储上。

public class SSLContextWithServer implements GetSSLSocket { 

    // 在这里进行服务器正式的名称的配置 
    private String[] serverCertificateNames = {"serverCertificateNames1" ,"serverCertificateNames2"}; 

    @Override 
    public SSLContext getSSLSocket() { 
        String[] caCertString = new String[serverCertificateNames.length]; 
        for(int i = 0 ; i < serverCertificateNames.length ; i++) { 
            try { 
                caCertString[i] = readCaCert(serverCertificateNames[i]); 
            } catch(Exception e) { 

            } 
        } 
        SSLContext mSSLContext = null; 
        try { 
            mSSLContext = SSLContextFactory.getInstance().makeContextWithServer(caCertString); 
        } catch(Exception e) { 

        } 
        return mSSLContext; 
    }

serverCertificateNames中定义了App所信任的证书名称(这些证书文件必须要放在指定的文件路径下,并其要保证名称相同),而后就可以加载服务端证书链到keystore,通过获取到的可信任并带有服务端证书的keystore,就可以用它来初始化自定义的SSLContext了:

@Override 
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { 
        try { 
            originalX509TrustManager.checkServerTrusted(chain, authType); 
        } catch(CertificateException originalException) { 
            try { 
                X509Certificate[] reorderedChain = reorderCertificateChain(chain); 
                CertPathValidator validator = CertPathValidator.getInstance("PKIX"); 
                CertificateFactory factory = CertificateFactory.getInstance("X509"); 
                CertPath certPath = factory.generateCertPath(Arrays.asList(reorderedChain)); 
                PKIXParameters params = new PKIXParameters(trustStore); 
                params.setRevocationEnabled(false); 
                validator.validate(certPath, params); 
            } catch(Exception ex) { 
                throw originalException; 
            } 
        } 
    }

(3) 跳过证书校验过程

和上面的过程类似,只不过这里提供的TrustManager不需要提供信任的证书集合,默认接受任意客户端证书即可:

public class AcceptAllTrustManager implements X509TrustManager { 

    @Override 
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { 
        //do nothing,接受任意客户端证书 
    } 

    @Override 
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { 
        //do nothing,接受任意服务端证书 
    } 

    @Override 
    public X509Certificate[] getAcceptedIssuers() { 
        return null; 
    }

而后构造相应的SSLContext:

public SSLContext makeContextToTrustAll() throws Exception { 
        AcceptAllTrustManager tm = new AcceptAllTrustManager(); 
        SSLContext sslContext = SSLContext.getInstance("TLS"); 
        sslContext.init(null, new TrustManager[] { tm }, null); 

        return sslContext; 
}

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer