Java-соединение и HTTPS-соединение без скачивания сертификата

Этот код подключается к сайту HTTPS, и я предполагаю, что не проверяю сертификат. Но почему мне не нужно устанавливать сертификат локально для сайта? Разве я не должен устанавливать сертификат локально и загружать его для этой программы, или он загружается за крышки? Является ли трафик между клиентом и удаленным сайтом зашифрованным при передаче?

import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.Reader; import java.net.URL; import java.net.URLConnection; import java.security.cert.X509Certificate; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; public class TestSSL { public static void main(String[] args) throws Exception { // Create a trust manager that does not validate certificate chains TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] certs, String authType) { } public void checkServerTrusted(X509Certificate[] certs, String authType) { } } }; // Install the all-trusting trust manager final SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); // Create all-trusting host name verifier HostnameVerifier allHostsValid = new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }; // Install the all-trusting host verifier HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); URL url = new URL("https://www.google.com"); URLConnection con = url.openConnection(); final Reader reader = new InputStreamReader(con.getInputStream()); final BufferedReader br = new BufferedReader(reader); String line = ""; while ((line = br.readLine()) != null) { System.out.println(line); } br.close(); } // End of main } // End of the class // 

Причина, по которой вам не нужно загружать сертификат локально, заключается в том, что вы явно не проверяли сертификат, и этот доверительный менеджер доверяет всем сертификатам.

Трафик по-прежнему будет зашифрован, но вы откроете соединение с атак Man-In-The-Middle: вы тайно общаетесь с кем-то, вы просто не уверены, что это ожидаемый сервер или возможный злоумышленник.

Если ваш сертификат сервера поступает из известного ЦС, часть пакета по умолчанию сертификатов ЦС в комплекте с JRE (обычно файл cacerts , см. Справочное руководство JSSE), вы можете просто использовать диспетчер доверия по умолчанию, вам не нужно что-нибудь здесь.

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

Но почему мне не нужно устанавливать сертификат локально для сайта?

Ну, код, который вы используете, явно предназначен для принятия сертификата без каких-либо проверок. Это не хорошая практика … но если это то, что вы хотите сделать, то (очевидно) нет необходимости устанавливать сертификат, явно игнорирующий ваш код.

Разве я не должен устанавливать сертификат локально и загружать его для этой программы, или он загружается за крышки?

Нет, и нет. См. Выше.

Является ли трафик между клиентом и удаленным сайтом зашифрованным при передаче?

Да. Однако проблема заключается в том, что, поскольку вы сказали ей доверять сертификату сервера без каких-либо проверок, вы не знаете, разговариваете ли вы с реальным сервером или каким-либо другим сайтом, который притворяется реальным сервером. Является ли это проблемой, зависит от обстоятельств.


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

В браузере установлен набор доверенных корневых сертификатов. В большинстве случаев, когда вы посещаете сайт «https», браузер может проверить, что сертификат сайта (в конечном счете, через цепочку сертификатов) защищен одним из этих доверенных сертификатов. Если браузер не распознает сертификат в начале цепочки как доверенный сертификат (или если сертификаты устарели или иным образом недействительны / неуместны), тогда он выведет предупреждение.

Java работает одинаково. В хранилище ключей JVM имеется набор доверенных сертификатов, и тот же процесс используется для проверки того, что сертификат защищен доверенным сертификатом.

Поддерживает ли клиент java https api некоторый тип механизма для автоматической загрузки информации сертификата?

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

Используйте последний X509ExtendedTrustManager вместо X509Certificate, как указано здесь: java.security.cert.CertificateException: сертификаты не соответствуют ограничениям алгоритма

  package javaapplication8; import java.io.InputStream; import java.net.Socket; import java.net.URL; import java.net.URLConnection; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509ExtendedTrustManager; /** * * @author hoshantm */ public class JavaApplication8 { /** * @param args the command line arguments * @throws java.lang.Exception */ public static void main(String[] args) throws Exception { /* * fix for * Exception in thread "main" javax.net.ssl.SSLHandshakeException: * sun.security.validator.ValidatorException: * PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: * unable to find valid certification path to requested target */ TrustManager[] trustAllCerts = new TrustManager[]{ new X509ExtendedTrustManager() { @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } @Override public void checkClientTrusted(X509Certificate[] certs, String authType) { } @Override public void checkServerTrusted(X509Certificate[] certs, String authType) { } @Override public void checkClientTrusted(X509Certificate[] xcs, String string, Socket socket) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] xcs, String string, Socket socket) throws CertificateException { } @Override public void checkClientTrusted(X509Certificate[] xcs, String string, SSLEngine ssle) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] xcs, String string, SSLEngine ssle) throws CertificateException { } } }; SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); // Create all-trusting host name verifier HostnameVerifier allHostsValid = new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }; // Install the all-trusting host verifier HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); /* * end of the fix */ URL url = new URL("http://sofru.miximages.com/java/panel.bmp"); URLConnection con = url.openConnection(); //Reader reader = new ImageStreamReader(con.getInputStream()); InputStream is = new URL(url.toString()).openStream(); // Whatever you may want to do next } } 

Java-соединение и HTTPS-соединение без скачивания сертификата

Если вы действительно хотите избежать загрузки сертификата сервера, используйте анонимный протокол, например, Anonymous Diffie-Hellman (ADH). Сертификат сервера не отправляется с ADH и друзьями.

Вы выбираете анонимный протокол с помощью setEnabledCipherSuites . Вы можете увидеть список наборов шифров, доступных с помощью getEnabledCipherSuites .

Связано: вот почему вы должны вызывать SSL_get_peer_certificate в OpenSSL. Вы получите X509_V_OK с анонимным протоколом, и именно так вы проверяете, использовался ли сертификат в обмене.

Но, как заявили Бруно и Стивен С, его плохая идея избежать проверок или использовать анонимный протокол.


Другой вариант – использовать TLS-PSK или TLS-SRP. Они также не требуют сертификатов сервера. (Но я не думаю, что вы можете их использовать).

Потребуется, вы должны быть предварительно подготовлены в системе, потому что TLS-PSK является секретным ключом, а TLS-SRP – безопасным удаленным паролем . Аутентификация является взаимной, а не только сервером.

В этом случае взаимная аутентификация обеспечивается тем свойством, что обе стороны знают общий секрет и приходят к такому же основному секрету; или один (или оба), и настройка канала не выполняется. Каждая сторона доказывает, что секрет – это «взаимная» часть.

Наконец, TLS-PSK или TLS-SRP не делают ничего глупого, например, кашляют пароль пользователя, как в веб-приложении, используя HTTP (или через HTTPS). Вот почему я сказал, что каждая сторона доказывает знание тайны …

Простое, но не чисто java-решение состоит в том, чтобы выложить curl из java, что дает вам полный контроль над тем, как выполняется запрос. Если вы просто делаете это для чего-то простого, это позволяет вам иногда игнорировать ошибки сертификата, используя этот метод. В этом примере показано, как сделать запрос на безопасный сервер с допустимым или недействительным сертификатом, передать в файл cookie и получить результат с помощью curl из java.

 import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; public class MyTestClass { public static void main(String[] args) { String url = "https://www.google.com"; String sessionId = "faf419e0-45a5-47b3-96d1-8c62b2a3b558"; // Curl options are: // -k: ignore certificate errors // -L: follow redirects // -s: non verbose // -H: add a http header String[] command = { "curl", "-k", "-L", "-s", "-H", "Cookie: MYSESSIONCOOKIENAME=" + sessionId + ";", "-H", "Accept:*/*", url }; String output = executeShellCmd(command, "/tmp", true, true); System.out.println(output); } public String executeShellCmd(String[] command, String workingFolder, boolean wantsOutput, boolean wantsErrors) { try { ProcessBuilder pb = new ProcessBuilder(command); File wf = new File(workingFolder); pb.directory(wf); Process proc = pb.start(); BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream())); BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream())); StringBuffer sb = new StringBuffer(); String newLine = System.getProperty("line.separator"); String s; // read stdout from the command if (wantsOutput) { while ((s = stdInput.readLine()) != null) { sb.append(s); sb.append(newLine); } } // read any errors from the attempted command if (wantsErrors) { while ((s = stdError.readLine()) != null) { sb.append(s); sb.append(newLine); } } String result = sb.toString(); return result; } catch (IOException e) { throw new RuntimeException("Problem occurred:", e); } } } 

Если вы используете какой-либо платежный шлюз, чтобы нажать любой URL-адрес, просто чтобы отправить сообщение, я использовал веб-просмотр, следуя ему: как загрузить URL-адрес https без использования ssl в веб-обозревателе Android

и сделать веб-просмотр в своей деятельности с видимостью. Что вам нужно сделать: просто загрузите этот веб-просмотр .. вот так:

  webViewForSms.setWebViewClient(new SSLTolerentWebViewClient()); webViewForSms.loadUrl(" https://bulksms.com/" + "?username=test&[email protected]&messageType=text&mobile="+ mobileEditText.getText().toString()+"&senderId=ATZEHC&message=Your%20OTP%20for%20A2Z%20registration%20is%20124"); 

Легко.

Вы получите это: SSLTolerentWebViewClient по этой ссылке: Как загрузить URL-адрес https без использования ssl в веб-обозревателе Android

  • ограничение отладки java ssl debug
  • C # Игнорировать ошибки сертификата?
  • Delphi: idHttp + SSL
  • Как я могу использовать WCF только с базовыми атрибутами, SSL и базовой аутентификацией в IIS?
  • Использование CERT Tapioca на VM
  • Https Connection Android
  • Как включить поддержку TLS 1.2 в Android-приложении (работает на Android 4.1 JB)
  • Можно ли заменить обычный разъем на SSLSocket?
  • Как всегда разрешать небезопасное соединение для определенного URL-адреса в хроме?
  • Использование сертификатов клиент / сервер для двухсторонней аутентификации SSL-сокета на Android
  • Принять самоподписанный сертификат ssl сервера в Java-клиенте
  • Interesting Posts
    Давайте будем гением компьютера.