Предисловие
Недавно необходимо решить проблему с HTTPS, поэтому я потратил время на изучение использования платформы Android HTTPS, и в то же время я также прочитал некоторые принципы HTTPS.
Принцип HTTPS
HTTPS (протокол передачи гипер текста) - это HTTP на основе SSL/TLS. Протокол HTTPS основан на протоколе HTTP, добавляя передачу рукопожатия SSL/TLS и шифрование данных, которая также принадлежит протоколу приложения. Следовательно, принцип изучения протокола HTTPS, наконец, является изучение протокола SSL/TLS.
Эффект протокола SSL/TLS
HTTP Communication без SSL/TLS не является зашифрованным общением.
1. Подслушивание риска: третьи стороны могут узнать о коммуникационном содержании.
2. Риск вмешивания: третья сторона может изменить содержание уведомления.
3. предшествующие риски: третьи стороны могут притворяться личности других, чтобы участвовать в общении.
Протокол SSL/TLS предназначен для решения этих трех рисков.
1. Вся информация представляет собой зашифрованную передачу, а третья сторона не может подслушивать.
2. Существует механизм проверки.
3. оснащен сертификатом ID, чтобы предотвратить выдачу личности.
Базовый процесс работы
Основная идея протокола SSL/TLS состоит в том, чтобы использовать метод шифрования открытого ключа, то есть клиент сначала запрашивает открытый ключ на сервере, а затем используйте открытый ключ для шифрования информации. , он будет расшифрован с собственным частным ключом. Но здесь вам нужно понять решение двух проблем.
1. Как обеспечить, чтобы открытый ключ не подделал?
Решение: поместите открытый ключ в цифровой сертификат. Пока сертификат заслуживает доверия, открытый ключ заслуживает доверия.
2. Количество шифрования общедоступного ключа слишком велика, как сократить потребление времени?
Решение: Каждый диалог, клиентская и сторона сервера генерирует «клавишу сеанса» (ключ сеанса) для шифрования информации. Поскольку «клавиша диалога» является симметричным шифрованием, скорость работы очень быстрая, а открытый ключ сервера используется только для шифрования самого «клавиша диалога», что снижает потребление времени зашифрованных операций.
Следовательно, базовый процесс протокола SSL/TLS подобен следующему:
1. Клиент запрошен на сервер и проверяет открытый ключ.
2. Обе стороны договариваются и генерируют «ключ диалога».
3. Две стороны используют «клавишу диалога» для выполнения зашифрованного общения.
Первые две ткани в вышеупомянутом процессе также называются «Стадия рукопожатия».
Подробный процесс стадии рукопожатия
«Стадия ручной работы» включает в себя четыре общения.
Клиент выдал запрос (ClientHello)
Прежде всего, клиент (обычно браузер) отправляет запрос на зашифрованную связь на сервер, который называется ClientHello запросом. На этом этапе клиент в основном предоставляет следующую информацию для сервера:
1. Поддерживаемая версия протокола, такая как версия TLS 1.0
2. Случайное число, сгенерированное клиентом, позже используется для генерации «клавиши диалога».
3. Поддерживаемые методы шифрования, такие как шифрование общедоступного ключа RSA.
4. Поддержка метода сжатия.
Следует отметить, что информация, отправленная клиентом, не включает доменное имя сервера. Другими словами, теоретический сервер может содержать только один веб -сайт, в противном случае неясно, какой цифровой сертификат которого предоставляет клиент. Вот почему на сервере обычно есть только один цифровой сертификат.
ServerHello
После того, как сервер получил клиент -запрос, он ответил на клиента, называемого ServerHello. Ответ сервера включает в себя следующее контент:
1. Подтвердите версию протокола зашифрованной связи, такую как версия TLS 1.0. Если браузер не соответствует версии, поддерживаемой сервером, сервер отключает зашифрованную связь.
2. Случайное число, сгенерированное сервером, позже используется для генерации «клавиша диалога».
3. Подтвердите используемый метод шифрования, такой как шифрование открытого ключа RSA.
4. Сертификат сервера.
В дополнение к вышеуказанной информации, если серверу необходимо подтвердить личность клиента, он будет включать другой запрос, попросив клиента предоставить «сертификат клиента». Например, финансовые учреждения часто позволяют только сертифицированным клиентам подключаться к своим собственным сетям и предоставляют USB -ключ для официальных клиентов, которые содержат сертификат клиента.
После того, как клиент отвечает на клиент, получил ответ сервера, сертификат сервера сначала проверяет сервер. Если сертификат не выдается доверенным учреждением, или доменное имя в сертификате не согласуется с фактическим доменным именем или истек срок Полем
Если нет проблем с сертификатом, клиент вытащит открытый ключ из сертификата. Затем отправьте следующие три сообщения на сервер.
1. Случайное число. Случайное количество сервера зашифровано, чтобы предотвратить нажатие.
2. Уведомление об изменениях кода, указывая на то, что последующая информация будет отправлена с помощью методов шифрования и ключей, согласованных обеими сторонами.
3. Руководство клиента заканчивает уведомление, указывая на то, что этап рукопожатия клиента закончилась. Этот элемент обычно является хэш -значением всего содержимого ранее отправленного на проверку сервера.
Первое случайное число выше-это третье случайное число, которое появляется на всей стадии рукопожатия, также известного как «Ключ-предварительный мастер». С помощью этого клиент и сервер имеют три случайных числа одновременно, а затем две стороны используют метод шифрования, согласованный заранее для генерации того же «сеанса», используемого в сеансе.
После того, как окончательный сервер ответов сервера получает третий случайный предварительный номер случайного номера от клиента, вычисляет «клавишу сеанса», используемый в сгенерированном сеансе. Затем отправьте следующую информацию клиенту.
1. Уведомление об изменениях кода, указывая на то, что последующая информация будет отправлена с помощью методов шифрования и ключей, согласованных обеими сторонами.
2. Руководство сервера заканчивает уведомление, указывая на то, что этап рукопожатия сервера закончился. Этот элемент также является хэш -значением всего предыдущего содержимого, которое используется для проверки клиента.
Рукопожатие конец
На этом этапе вся этап рукопожатия закончилась. Затем клиент и сервер вводят зашифрованную связь, которая использует обычный протокол HTTP, но использует содержимое шифрования «сеанса».
Сервер построил виртуальный сайт HTTPS на основе Nginx
Предыдущая статья подробно описана, как генерировать сертификаты SSL на стороне сервера и создать HTTPS -сервер на основе Nginx, ссылка: Nginx создает HTTPS -сервер
Реализация Android Communication Communication
По разным причинам используйте класс httpclicent, чтобы объяснить, как Android строит HTTPS -соединение. Демонстрация кода выглядит следующим образом.
MainActivity.java
Пакет Com. Пример. client.httpclient; Импорт Android.log; Super.oncreate (SaveNstanceState); {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 = httpresponse.getstatusline (); (http response.getentity (). getContent (), "utf-8"); (Exception e) {log.e ("https", e.getmessage ()); ) {Log.e ("https", e.getmessage ()); .toString ());}}}}
Httputils.java
Пакет Com. conn.scheme.scheme; .apache.params.basichtpparams; Newttpare ms (); eregistry (); ); {Basichtpparams params = new basichtpparams (); .register (новая схема ( "Http", PlainsocketSocketSockeCockfactory (), 80); Httpclient getpect (контекст) {basichttpparams params = new basichtpparams (); S, True); Schemeregistry () ;; }}
Activity_main.xml
<linearlayout xmlns: android = "http://schemas.android.com/apk/res/android" xmlns: tools = "http://schemas.android.com" Android: Lay Out_width = "match_parent" Android: Layout_Height = "Match_pareat" Android: Orientation = "vertical"> <кнопка 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": textsize = "16sp" / / /> </ Linearlayout>
Android использует Defaulthttpclient для установления HTTPS -соединения.
Schreg.register (новая схема ("https", sslsocketfactory.getSocketFactory (), 443));
Присоединяйтесь к поддержке HTTPS, вы можете эффективно установить HTTPS -соединение, такое как «https://www.google.com.hk», но это невозможно получить доступ на основе сервера HTTPS, созданного Nginx, потому что он есть Не используется система, которая будет использоваться системой.
Используйте пользовательский сертификат и игнорируйте проверенный метод подключения HTTPS
Метод решения сертификата не распознается системой, чтобы пропустить проверку системы. Если вы хотите пропустить проверку системы, вы больше не можете использовать системную стандартную SSL SocketFactory. Затем, чтобы пропустить проверку в этой пользовательской SSL SocketFactory, вам также необходимо настроить TrustManager, который игнорирует все проверки, то есть Trustall.
Пакет Com.ment.photocrop; Import Java.security.nosuchalgorithmexception; .xl.x509trustmanager; Super (TrustStore); New x509trustmanager () {@override public x509certified [] geta cceptedisssuers () {return null;} @override public void ceckservertrusted (x509certified [] Цепь, строка Auttype) Throws {} @public void ecketcrusteded (x509certied [] string aithlype owntyt ) Throws Sertivexception {}}; (Спекнет, строковый порт, логический автоклоз), неизвестный Hostexception {return sslcontext.getSocketFactory (). );
В то же время вам необходимо изменить метод регистрации DefaultTTPClient, чтобы перейти на созданный вами SSLSocket:
Public Static httpclient getCustomClient () {Basichtpparams params = new Basichttparams (); .register (новая схема ("http ", PlainsocketCeactory.getSocketFactory (), 80)); Schreg.Register (" httpsoc "kectory.getSocketFactory (), 443)); ClientConnectionManager connmgr = new ThreadsafeclientConnnagnager (Params, schrege); return new defaultpclient (connemmgr, pames);
Таким образом, вы можете успешно получить доступ к виртуальному сайту HTTPS на основе NGINX.
дефект:
Однако, хотя это решение использует HTTPS, содержимое связи клиента и сервера зашифруется, программа понюхания не может получить содержание передачи, но она не может противостоять «атаке посредника». Например, настройте DNS во внутренней сети, проанализируйте доменное имя целевого сервера на локальный адрес, а затем используйте промежуточный сервер в качестве агента на этом адресе. сертификаты. Таким образом, весь коммуникационный контент пройдет с этим агентом, и клиент не воспринимает, что вызвано сертификатом общедоступного ключа неверного сервера клиента.
Используйте пользовательский сертификат для установления подключения к HTTPS
Чтобы предотвратить «посредническую атаку», которая может быть вызвана приведенной выше схемой, мы можем загрузить сертификат открытого ключа сервера, а затем собрать сертификат открытого ключа в приложение Android, чтобы проверить сертификат само по себе.
Генерировать магазин ключей
Чтобы проверить пользовательский сертификат, мы должны сначала собрать сертификат в приложение. Сертификат здесь относится к открытому ключу целевого сервера, который может быть получен из файла .crt или .pem, настроенный веб -сервером. В то же время вам нужно настроить Bouldcastle.
Keytool -Importcert -v -TrustCacerts -Alias Пример -file www.example.com.crt -KeyStore Пример. Jre/lib/ext/bcprov-jdk16-145.jar-storepass pw123456
После запуска содержимое сертификата будет отображаться, и подскажет, что вы можете ввести y ввод.
После успешного производства файла ключа, поместите его в каталог Res/RAW приложения приложения.
Использование пользовательского магазина ключей для реализации идей соединений аналогично Trushall.
Пакет Com. java.security.unrecoverablekeexception; Public Statice SSLSOCTECTORY EXT) ;} Catch (Exception e) {e.printstacktrace (); input = null;}}}}}}}}}}}}}
В то же время вам необходимо изменить метод регистрации DefaultTTPClient, чтобы перейти на созданный вами SSLSocket:
Public Static httpclient getspecilkeystoreclient (контекст) Schemeregistry Schreg = новая сэмрегистрация ( ); Params);}}