Prefacio
Recientemente, se debe resolver un problema relacionado con HTTPS, por lo que pasé tiempo aprendiendo el uso de la plataforma Android HTTPS, y al mismo tiempo, también leo algunos principios de HTTPS.
Principio HTTPS
HTTPS (Protocolo de transferencia Hyper Text) es un HTTP basado en SSL/TLS. El protocolo HTTPS se basa en el protocolo HTTP, que agrega el apretón de manos SSL/TLS y la transmisión de cifrado de datos, que también pertenece al protocolo de capa de aplicación. Por lo tanto, el principio de estudiar el protocolo HTTPS es finalmente estudiar el protocolo SSL/TLS.
Efecto de protocolo SSL/TLS
La comunicación HTTP sin SSL/TLS no es una comunicación cifrada.
1. Riesgo de espía: los terceros pueden aprender sobre el contenido de comunicación.
2. Riesgo de manipulación: terceros pueden modificar el contenido de la notificación.
3. Precaja los riesgos: los terceros pueden fingir ser la identidad de los demás para participar en la comunicación.
El protocolo SSL/TLS está diseñado para resolver estos tres riesgos.
1. Toda la información es transmisión cifrada, y el tercero no puede escuchar.
2. Hay un mecanismo de verificación.
3. Equipado con un certificado de identificación para evitar que la identidad se haga pasar por su parte.
Proceso de operación básica
La idea básica del protocolo SSL/TLS es utilizar el método de cifrado de la clave pública, es decir, el cliente primero solicita la clave pública al servidor y luego usa la clave pública para la información cifrada. , se descifrará con su propia clave privada. Pero aquí debe comprender la solución a los dos problemas.
1. ¿Cómo garantizar que la clave pública no esté manipulada?
Solución: Coloque la clave pública en un certificado digital. Mientras el certificado sea creíble, la clave pública es creíble.
2. La cantidad de cifrado de clave pública es demasiado grande, ¿cómo reducir el consumo de tiempo?
Solución: cada diálogo, el cliente y el lado del servidor generan una "clave de sesión" (clave de sesión) para cifrar información. Debido a que la "clave de diálogo" es el cifrado simétrico, la velocidad de operación es muy rápida, y la clave pública del servidor solo se usa para cifrar la "clave de diálogo" en sí, lo que reduce el consumo de tiempo de operaciones cifradas.
Por lo tanto, el proceso básico del protocolo SSL/TLS es así:
1. El cliente se solicita al servidor y verifica la clave pública.
2. Ambas partes negocian y generan la "clave de diálogo".
3. Las dos partes usan la "clave de diálogo" para realizar una comunicación cifrada.
Las dos primeras telas en el proceso anterior también se llaman "Etapa de apretón de manos".
El proceso detallado de la etapa de apretón de manos
"Handhake Stage" implica cuatro comunicación.
El cliente emitió una solicitud (Clienthello)
En primer lugar, el cliente (generalmente navegador) envía una solicitud de comunicación encriptada al servidor, que se llama solicitud Clienthello. En este paso, el cliente proporciona principalmente la siguiente información al servidor:
1. Versión de protocolo compatible, como la versión TLS 1.0
2. El número aleatorio generado por un cliente se usa más tarde para generar la "clave de diálogo".
3. Métodos de cifrado de apoyo, como el cifrado de clave pública RSA.
4. Método de compresión de soporte.
Cabe señalar que la información enviada por el cliente no incluye el nombre de dominio del servidor. En otras palabras, el servidor teórico solo puede contener un sitio web, de lo contrario no estará claro a qué certificado digital del que proporciona al cliente. Es por eso que un servidor generalmente tiene solo un certificado digital.
Servidor
Después de que el servidor recibió una solicitud del cliente, respondió al cliente, llamado ServerHello. La respuesta del servidor incluye el siguiente contenido:
1. Confirme la versión de protocolo de comunicación cifrada, como la versión TLS 1.0. Si el navegador es inconsistente con la versión compatible con el servidor, el servidor apaga la comunicación cifrada.
2. El número aleatorio generado por un servidor se usa más tarde para generar la "clave de diálogo".
3. Confirme el método de cifrado utilizado, como el cifrado de clave pública RSA.
4. Certificado del servidor.
Además de la información anterior, si el servidor necesita confirmar la identidad del cliente, incluirá otra solicitud, solicitando al cliente que proporcione un "certificado del cliente". Por ejemplo, las instituciones financieras a menudo solo permiten a los clientes certificados conectarse a sus propias redes y proporcionarán la clave USB a los clientes formales, que contiene un certificado de cliente.
Después de que el cliente responde al cliente recibió la respuesta del servidor, el certificado del servidor verifica primero el servidor. Si el certificado no es emitido por la institución de confianza, o el nombre de dominio en el certificado es inconsistente con el nombre de dominio real, o el certificado ha expirado, mostrará una advertencia a los visitantes y si continúa comunicando desde la elección .
Si no hay problema con el certificado, el cliente sacará la clave pública del certificado. Luego envíe los siguientes tres mensajes al servidor.
1. Un número aleatorio. El número aleatorio del servidor está encriptado para evitar ser TAP.
2. Notificación de cambios en el código, lo que indica que la información posterior se enviará con los métodos de cifrado y las claves acordadas por ambas partes.
3. El apretón de manos del cliente finaliza el aviso, lo que indica que la etapa de apretón de manos del cliente ha terminado. Este elemento suele ser el valor hash de todos los contenidos de la verificación de servidor enviada previamente.
El primer número aleatorio anterior es el tercer número aleatorio que aparece en toda la etapa de apretón de manos, también conocida como "clave pre-maestro". Con él, el cliente y el servidor tienen tres números aleatorios al mismo tiempo, y luego las dos partes usan el método de cifrado acordado por adelantado generar la misma "clave de sesión" utilizada en la sesión.
Después de la respuesta final del servidor recibe la tercera clave de pre-maestro de número aleatorio del cliente, calcula la "clave de sesión" utilizada en la sesión generada. Luego envíe la siguiente información al cliente.
1. Notificación de cambios en el código, lo que indica que la información posterior se enviará con los métodos de cifrado y las claves acordadas por ambas partes.
2. El apretón de manos del servidor finaliza el aviso, lo que indica que la etapa de apretón de manos del servidor ha terminado. Este elemento también es el valor hash de todos los contenidos anteriores, que se utiliza para la verificación del cliente.
Endshake de manos
En este punto, toda la etapa de apretón de manos ha terminado. A continuación, el cliente y el servidor ingresan a la comunicación cifrada, que utiliza un protocolo HTTP ordinario, pero utiliza el contenido de cifrado "Clave de sesión".
El servidor creó un sitio virtual HTTPS basado en Nginx
El artículo anterior introdujo en detalle cómo generar certificados SSL en el lado del servidor y construir un servidor HTTPS basado en NGINX, enlace: Nginx construye un servidor HTTPS
Implementación de Android de la comunicación HTTPS
Por varias razones, use la clase HTTPClicent para explicar cómo Android construye una conexión HTTPS. La demostración del código es la siguiente.
MainActivity.java
paquete com.example.photocrop; Client.httpClient; Importar android.util.log; Super.oncreate (saveDInStancate); ) {runhttpsconnecti on ();}}); httpstask.getStatus () == statushed) {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) {statusline statusline = httpesponse.getStatusline (); (http respuesta.getEntity (). getContent (), "utf-8"); (Excepción e) {log.e ("https", e.getMessage ()); ) {Log.e ("https", e.getMessage ()); .ToString ());}}}}
Httputils.java
paquete com.example.photocrop; Conn.scheme.scheme; .Apache.Params.BasichTParams; Newttpara MS (); eregistry (); ); ) {BasichtParams Params = new BasichttParams (); . Register (nuevo esquema ( "Http", PlainsocketTetSocketFactory (), 80); HttpClient Getspect (contexto de contexto) {BASICHTTPARAMS Params = new BasichtParams (); S, verdadero); SchemeRegistry (); }}
Activity_Main.xml
<linealLayout xmlns: android = "http://schemas.android.com/apk/res/android" xmlns: herramientas = "http://schemas.android.com" Android: Lay Out_width = "Match_parent" Android: Layout_Height = "Match_pareat" Android: Orientation = "Vertical"> <Button Android: id = "@+id/create_button" Android: Layout_ "matriz" 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" / /> </ LinealLayout>
Android utiliza DeFaulThTTPClient para establecer una conexión HTTPS.
Schreg.register (nuevo esquema ("https", sslsocketfactory.getSocketFactory (), 443));
Únase al soporte de HTTPS, puede establecer de manera efectiva la conexión HTTPS, como "https://www.google.com.hk", pero no es posible acceder a usted mismo en función del servidor HTTPS construido por NGINX, porque es es No utilizado por el sistema para ser utilizado por el sistema.
Use un certificado personalizado e ignore el método de conexión HTTPS verificado
El método para resolver el certificado no es reconocido por el sistema es omitir la verificación del sistema. Si desea omitir la verificación del sistema, ya no puede usar el SSL SLockFactory estándar del sistema. Luego, para omitir la verificación en este SSL SCOCKECTORY personalizado, también debe personalizar un fideicomiso, que ignora todas las verificaciones, es decir, confianza.
paquete com.example.photocrop; Importar java.security.nosuchalgorithmexception; .xl.x509TrustManager; Ception {Super (TrustStore); Nuevo x509TrustManager () {@Override public x509Certified [] geta cceptedissSuers () {return null;} @Override public void checkServerTrusted (x509certified [] cadena, cadena authtype) lanza {} @anular public void checkClitTrusted (x509certified [] cadena, cadena authtype) lanza) ) Tira certificada {}}; (Socket Socket, Puerto de cadena, Boolean AutoClose) ion, Desconocidohostoxception {return sslContext.getSocketFactory (). ));
Al mismo tiempo, debe modificar el método de registro del defaultTTPClient para cambiar al sslsocket que construyó:
Public HttpClient GetCustomClient () {BasichtParams Params = New BasichttParams (); .Register (nuevo esquema ("http ", PlainSocketFactory.getSocketFactory (), 80)); schreg.register (" httpsoc "kectory.getSocketFactory (), 443))); ClientConnectionManager connmgr = new ThreadSafeClientConnManager (params, schreg); return New FredettpClient (connemmgr, params);}
De esta manera, puede acceder con éxito al sitio virtual HTTPS basado en Nginx.
defecto:
Sin embargo, aunque esta solución usa HTTPS, el contenido de comunicación del cliente y el servidor está encriptado, el programa de olpio no puede obtener el contenido de la transmisión, pero no puede resistir el "ataque intermediario". Por ejemplo, configure un DNS en la red interna, analice el nombre de dominio del servidor de destino en una dirección local y luego use un servidor intermedio como agente en esta dirección. certificados. De esta manera, todo el contenido de comunicación pasará a este agente, y el cliente no percibirá, que es causado por el certificado de clave pública del servidor de no verificación del cliente.
Use un certificado personalizado para establecer una conexión HTTPS
Para evitar el "ataque intermediario" que puede ser causado por el esquema anterior, podemos descargar el certificado de clave pública junto al servidor y luego compilar el certificado de clave pública a la aplicación Android para verificar el certificado por sí solo.
Generar la tienda de claves
Para verificar el certificado personalizado, primero debemos compilar el certificado a la aplicación. El certificado aquí se refiere a la clave pública del servidor de destino, que se puede obtener del archivo .crt o el archivo .pem configurado por el servidor web. Al mismo tiempo, debe configurar Bouundcastle.
KeyTool -ImportCert -V -TrustCacerts -alias Ejemplo -file www.example.com.crt -keystore Ejemplo.bks -storetype bks -providerclass rovider.boundcastleprovider -providerpath/home/wzy/descargas/java/jdk1 .7.0_60 /60 /60/60 /60 Jre/lib/ext/bcprov-jdk16-145.Jar-storePass PW123456
Después de ejecutar, el contenido del certificado se mostrará y le solicitará que confirme si puede ingresar y ingresar.
Después de que la producción del archivo del almacén de claves sea exitosa, colóquelo en el directorio RES/RAW de la aplicación de la aplicación.
El uso del almacén de claves personalizado para implementar ideas de conexión es similar a Trushall.
paquete com.example.photocrop; java.security.uncoverablekeyException; } Public sslsocketfactory ext) {inputStream input = null; ;} Catch (Exception e) {E.PrintStackTrace (); input = null;}}}}}}}}}}}}}
Al mismo tiempo, debe modificar el método de registro del defaultTTPClient para cambiar al sslsocket que construyó:
Public static httpclient getSpecilkeyStoreclient (contexto de contexto) {BASICHTPARAMS PARAMS = new BasichttParams (); SchemeGistry Schreg = New Schemeregistry ( ); Params);}}