Использование BouncyCastle для простого HTTPS-запроса - PullRequest
1 голос
/ 17 ноября 2011

Вот упрощенная версия кода, который я использую для выполнения простых HTTPS-запросов:

// Assume the variables host, file and postData have valid String values

final URL url = new URL("https", host, file);
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();

connection.setRequestMethod("POST");
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestProperty("Content-length", String.valueOf(postData.length()));

final DataOutputStream output = new DataOutputStream(connection.getOutputStream());
output.writeBytes(postData);
output.close();

final InputStream input = new DataInputStream(connection.getInputStream());

for (int c = input.read(); c != -1; c = input.read()) {
  System.out.print((char) c);
}

System.out.println();

input.close();

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

Теперь я получаю сообщения об ошибках «Не удалось сгенерировать пару ключей DH» и «Основной размер должен быть кратен 64, и может варьироваться от 512 до 1024 (включительно)», упомянутых в этом вопросе:

Java: почему SSL-квитирование дает исключение «Не удалось сгенерировать пару ключей DH»?

Оказывается, это известная ошибка в Java, и рекомендуется использовать реализацию JCE BouncyCastle.

Мой вопрос ... как мне использовать BouncyCastle для чего-то подобного? Или есть еще альтернативы?

Отказ от ответственности: я очень мало знаю и интересуюсь криптологией и базовой технологией, которая делает возможным HTTPS-запросы. Скорее, я бы предпочел сосредоточиться на логике своего приложения и позволить различным библиотекам решать проблемы низкого уровня.

Я проверил веб-сайт BouncyCastle и документацию и Googled, чтобы узнать больше о JCE и т. Д., Но в целом это довольно сложно, и я не смог найти простых примеров кода для выполнения чего-то вроде приведенного выше кода.

Ответы [ 4 ]

3 голосов
/ 19 октября 2015

В следующем примере кода используются jdk1.6.0_45 и bcprov-jdk15on-153.jar для выполнения простого запроса https:

import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.Socket;

import org.bouncycastle.crypto.tls.CertificateRequest;
import org.bouncycastle.crypto.tls.DefaultTlsClient;
import org.bouncycastle.crypto.tls.TlsAuthentication;
import org.bouncycastle.crypto.tls.TlsClientProtocol;
import org.bouncycastle.crypto.tls.TlsCredentials;

public class TestHttpClient {
    // Reference: http://boredwookie.net/index.php/blog/how-to-use-bouncy-castle-lightweight-api-s-tlsclient/
    //            bcprov-jdk15on-153.tar\src\org\bouncycastle\crypto\tls\test\TlsClientTest.java
    public static void main(String[] args) throws Exception {
        java.security.SecureRandom secureRandom = new java.security.SecureRandom();
        Socket socket = new Socket(java.net.InetAddress.getByName("www.google.com"), 443);
        TlsClientProtocol protocol = new TlsClientProtocol(socket.getInputStream(), socket.getOutputStream(),secureRandom);
        DefaultTlsClient client = new DefaultTlsClient() {
            public TlsAuthentication getAuthentication() throws IOException {
                TlsAuthentication auth = new TlsAuthentication() {
                    // Capture the server certificate information!
                    public void notifyServerCertificate(org.bouncycastle.crypto.tls.Certificate serverCertificate) throws IOException {
                    }

                    public TlsCredentials getClientCredentials(CertificateRequest certificateRequest) throws IOException {
                        return null;
                    }
                };
                return auth;
            }
        };
        protocol.connect(client);

        java.io.OutputStream output = protocol.getOutputStream();
        output.write("GET / HTTP/1.1\r\n".getBytes("UTF-8"));
        output.write("Host: www.google.com\r\n".getBytes("UTF-8"));
        output.write("Connection: close\r\n".getBytes("UTF-8")); // So the server will close socket immediately.
        output.write("\r\n".getBytes("UTF-8")); // HTTP1.1 requirement: last line must be empty line.
        output.flush();

        java.io.InputStream input = protocol.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(input));
        String line;
        while ((line = reader.readLine()) != null)
        {
            System.out.println(line);
        }
    }
}
1 голос
/ 17 ноября 2011

Здесь - страница о том, как зарегистрировать провайдера JCE Bouncy Castle.Если вы выберете второй вариант, убедитесь, что значение N (порядок предпочтений) таково, что оно предшествует поставщику Sun JCE (и соответственно измените порядок предпочтений при регистрации поставщика Sun JCE).

0 голосов
/ 12 июля 2018

У меня та же проблема, и я решил ее, включая следующие строки

Security.addProvider(new BouncyCastleProvider());
System.setProperty("https.protocols", "TLSv1");
0 голосов
/ 18 ноября 2011

Я нашел другое решение (хотя и по ссылке, размещенной srkavin), которое даже не требует использования BouncyCastle:

После загрузки «Расширенных файлов политики шифрования Java (JCE) из политики неограниченной юрисдикции» из Сайт загрузки Java и замена файлов в моей JRE, приведенный выше код начал работать без каких-либо изменений.

...