Intereting Posts
Может ли моя активность получить результат отправки MMI? Android: передача параметров на вкладку Безопасный способ разрешения конфликта зависимостей для Диска и Dropbox? Строительный проект андроида производит ошибку 2 В API GoogleCloudMessaging, как обрабатывать обновление или истечение срока действия регистрационного удостоверения? Ошибка построения несоответствия архитектуры процессора CORS + Android Webview, не работает на устройстве (но работает на эмуляторе) База данных SQLite для базы данных SQLite с индексом 2048 кб не выполнена Как конвертировать пиксели в dip (независимые от плотности пиксели) в Android Установить цвет кнопки ClearView SearchView Как играть несколько сигналов тревоги с помощью уведомления? Как перезапустить убитую службу автоматически? Как настроить репозитории Git для разработки Android в Eclipse? Как серверы подключения GCM отправляют сообщения на устройство Android? ActivityManager: Исключение при запуске java.lang.IllegalArgumentException: val.length> 91

Как переопределить шифрованный список, отправленный на сервер Android при использовании HttpsURLConnection?

Во время переговоров TLS клиенты отправляют на сервер список поддерживаемых шифров, сервер выбирает один, и начинается шифрование. Я хочу изменить этот шифрованный список, отправленный на сервер Android, когда я использую HttpsURLConnection для связи.

Я знаю, что я могу использовать setSSLSocketFactory HttpsURLConnection объекта HttpsURLConnection чтобы настроить его на использование SSLSocketFactory . Это полезно, когда я хочу изменить trustmanager и т. Д., Используемый SSLSocket возвращенный SSLSocketFactory .

Я знаю, что в целом этот список ciphersuite можно редактировать с помощью объекта SSLParameters и передавать его в SSlsocket или SSLEngine с использованием методов, которые они предоставляют.

НО SSLSocketFactory , похоже, не раскрывает такие методы!

Я не могу найти способ изменить SSLParameters возвращаемых объектов SSLSocket созданных SSLSocketFactory я HttpsURLConnection в HttpsURLConnection .

Что делать?

Я думаю, это также относится к Java в целом, а не только для Android. Возможно, есть способ OO (например, расширить SSLSocketFactory и предоставить это HttpsURLConnection ?)

Этот фрагмент кода немного сырой. Используйте с осторожностью.

 public class PreferredCipherSuiteSSLSocketFactory extends SSLSocketFactory { private static final String PREFERRED_CIPHER_SUITE = "TLS_RSA_WITH_AES_128_CBC_SHA"; private final SSLSocketFactory delegate; public PreferredCipherSuiteSSLSocketFactory(SSLSocketFactory delegate) { this.delegate = delegate; } @Override public String[] getDefaultCipherSuites() { return setupPreferredDefaultCipherSuites(this.delegate); } @Override public String[] getSupportedCipherSuites() { return setupPreferredSupportedCipherSuites(this.delegate); } @Override public Socket createSocket(String arg0, int arg1) throws IOException, UnknownHostException { Socket socket = this.delegate.createSocket(arg0, arg1); String[] cipherSuites = setupPreferredDefaultCipherSuites(delegate); ((SSLSocket)socket).setEnabledCipherSuites(cipherSuites); return socket; } @Override public Socket createSocket(InetAddress arg0, int arg1) throws IOException { Socket socket = this.delegate.createSocket(arg0, arg1); String[] cipherSuites = setupPreferredDefaultCipherSuites(delegate); ((SSLSocket)socket).setEnabledCipherSuites(cipherSuites); return socket; } @Override public Socket createSocket(Socket arg0, String arg1, int arg2, boolean arg3) throws IOException { Socket socket = this.delegate.createSocket(arg0, arg1, arg2, arg3); String[] cipherSuites = setupPreferredDefaultCipherSuites(delegate); ((SSLSocket)socket).setEnabledCipherSuites(cipherSuites); return socket; } @Override public Socket createSocket(String arg0, int arg1, InetAddress arg2, int arg3) throws IOException, UnknownHostException { Socket socket = this.delegate.createSocket(arg0, arg1, arg2, arg3); String[] cipherSuites = setupPreferredDefaultCipherSuites(delegate); ((SSLSocket)socket).setEnabledCipherSuites(cipherSuites); return socket; } @Override public Socket createSocket(InetAddress arg0, int arg1, InetAddress arg2, int arg3) throws IOException { Socket socket = this.delegate.createSocket(arg0, arg1, arg2, arg3); String[] cipherSuites = setupPreferredDefaultCipherSuites(delegate); ((SSLSocket)socket).setEnabledCipherSuites(cipherSuites); return socket; } private static String[] setupPreferredDefaultCipherSuites(SSLSocketFactory sslSocketFactory) { String[] defaultCipherSuites = sslSocketFactory.getDefaultCipherSuites(); ArrayList<String> suitesList = new ArrayList<String>(Arrays.asList(defaultCipherSuites)); suitesList.remove(PREFERRED_CIPHER_SUITE); suitesList.add(0, PREFERRED_CIPHER_SUITE); return suitesList.toArray(new String[suitesList.size()]); } private static String[] setupPreferredSupportedCipherSuites(SSLSocketFactory sslSocketFactory) { String[] supportedCipherSuites = sslSocketFactory.getSupportedCipherSuites(); ArrayList<String> suitesList = new ArrayList<String>(Arrays.asList(supportedCipherSuites)); suitesList.remove(PREFERRED_CIPHER_SUITE); suitesList.add(0, PREFERRED_CIPHER_SUITE); return suitesList.toArray(new String[suitesList.size()]); } } 

Когда вы хотите его использовать.

  HttpsURLConnection connection = (HttpsURLConnection) (new URL(url)) .openConnection(); SSLContext context = SSLContext.getInstance("TLS"); TrustManager tm[] = {new SSLPinningTrustManager()}; context.init(null, tm, null); SSLSocketFactory preferredCipherSuiteSSLSocketFactory = new PreferredCipherSuiteSSLSocketFactory(context.getSocketFactory()); connection.setSSLSocketFactory(preferredCipherSuiteSSLSocketFactory); connection.connect(); 

Спасибо вам.

Я связал технику в ответе @ ThinkChris 1 на мертвый простой вызов метода. Вы можете использовать библиотеку NetCipher для получения современной конфигурации TLS при использовании HttpsURLConnection Android. NetCipher настраивает экземпляр HttpsURLConnection для использования наилучшей поддерживаемой версии TLS, удаляет поддержку SSLv3 и настраивает лучший набор шифров для этой версии TLS. Сначала добавьте его в свой build.gradle :

 compile 'info.guardianproject.netcipher:netcipher:1.2' 

Или вы можете загрузить netcipher-1.2.jar и включить его прямо в свое приложение. Затем вместо вызова:

 HttpURLConnection connection = (HttpURLConnection) sourceUrl.openConnection(); 

Назовите это:

 HttpsURLConnection connection = NetCipher.getHttpsURLConnection(sourceUrl); 

Если вы хотите специально настроить этот список шифров, вы можете проверить там код. Но большинству людей не нужно думать о списке шифров, вместо этого он должен использовать общие рекомендации по умолчанию.

Этот код сработал чудесами для неожиданного javax.net.ssl.SSLHandshakeException .

Обновление до jdk1.8.0_92 и файлов политики неограниченной прочности Oracle JCE не помогло, и я безуспешно пытался применить определенные SSLParameters к HttpsUrlConnection .

В частности, попытка использования HttpsUrlConnection для чтения https://www.adrbnymellon.com приводит к следующей ошибке:

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

Этот сайт работал нормально до 4/15/2016, а затем начал сбой. Я считаю, что неудача вызвана тем, что веб-сайт прекратил поддержку SSLv2Hello и SSLv3 из-за уязвимости DROWN. См. Это для отличного анализа.

Доступ к веб-сайту начал работать, изменив код с изменениями только на 2 константы:

 private static final String PREFERRED_CIPHER_SUITE = "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"; SSLContext context = SSLContext.getInstance("TLSv1.2"); 

Надеюсь, это поможет кому-то другому.