Using BouncyCastle for a simple HTTPS query

mjo*_*ble 5 java ssl https bouncycastle jce

Here's a simplified version of the code I'm using to perform simple HTTPS requests:

// 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();
Run Code Online (Sandbox Code Playgroud)

This used to work well for connecting to our server (and still does if I use http as the protocol) until recently when some security upgrades were done.

Now it's giving me the "Could not generate DH keypair" and "Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive)" errors mentioned in this question:

Java: Why does SSL handshake give 'Could not generate DH keypair' exception?

Turns out it's a known bug in Java and the recommendation is to use BouncyCastle's JCE implementation.

My question is... how do I use BouncyCastle for something like this? Or are there more alternatives?

Disclaimer: I have very little knowledge of and interest in cryptology and the underlying technology that makes HTTPS queries possible. Rather, I'd prefer to focus on my application logic and let various libraries take care of low level issues.

我查看了 BouncyCastle 网站和文档并通过 Google 搜索以了解有关 JCE 等的更多信息,但总而言之,它非常令人难以抗拒,而且我无法找到任何简单的代码示例来执行类似上述代码的操作。

ora*_*oon 5

以下示例代码使用 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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


mjo*_*ble 1

我找到了一个不同的解决方案(尽管通过 srkavin 发布的链接),甚至不需要使用 BouncyCastle:

Java 下载站点下载“Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files”并替换我的 JRE 中的文件后,上述代码无需任何修改即可开始工作。