Intereting Posts
Запустить Android-виджет Неверный фрагмент в ViewPager получает onContextItemВыбранный вызов Транзитивные зависимости AAR в Maven Как получить NEW width / height корневого макета в onConfigurationChanged? OnItemClickListener не работает должным образом, когда адаптер содержит кнопку с onClickListener Взаимодействующая с оболочкой оболочка для CoordinatorLayout и BottomSheetBehavior Использование специального приложения с InstrumentationTestCase Android – добавьте фрагмент с настраиваемыми параметрами Android / Eclipse: где я могу найти папку /Users/USER_NAME/.android/debug.keystore? Нарисуйте пузырь программно В Google Plus дважды появляется диалоговое окно «Выбрать учетную запись» Сравнить два изображения в android Получение ошибки с использованием ScrimInsetFrameLayout Изменение центральной позиции эффекта эффекта пульсации для андроида. Как использовать greenrobot для передачи данных в действие или фрагмент, который еще не был инициализирован?

Как переопределить шифрованный список, отправленный на сервер 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 ?)

Solutions Collecting From Web of "Как переопределить шифрованный список, отправленный на сервер Android при использовании 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"); 

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