java - 将证书添加到 BouncyCaSTLe TLSSocketConnectionFactory

标签 java bouncycastle

对如何将证书包含到 Bouncy CaSTLe TLSSocketConnectionFactory 有疑问?

例如,我在以前的版本中使用过这段代码,并且它适用于 TLS1.0:

        SSLContext sslcontext = SSLContext.getInstance("TLS");
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        InputStream is = new FileInputStream("c:/cert/test-tls.cer");
        InputStream caInput = new BufferedInputStream(is);
        Certificate ca;
        try {
            ca = cf.generateCertificate(caInput);
        } finally {
            caInput.close();
        }
        String keyStoreType = KeyStore.getDefaultType();
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);

        // Create a TrustManager that trusts the CAs in our KeyStore
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);

        TrustManager[] tm = tmf.getTrustManagers();
        sslcontext.init(kmf.getKeyManagers(), tm, null);
        SSLSocketFactory sslSocketFactory = sslcontext.getSocketFactory();
        HttpsURLConnection.setDefaultSSLSocketFactory(sslSocketFactory);

现在我必须使用 Bouncy CaSTLe,因为 Java 1.6 不支持 TLS1.1/TLS1.2

所以第一步是扩展 SSLSocketFactory 类..
我的是:

@Override
    public void startHandshake() throws IOException {
        tlsClientProtocol.connect(new DefaultTlsClient() {
            @Override
            public Hashtable<Integer, byte[]> getClientExtensions() throws IOException {
                Hashtable<Integer, byte[]> clientExtensions = super.getClientExtensions();
                if (clientExtensions == null) {
                    clientExtensions = new Hashtable<Integer, byte[]>();
                }

                //Add host_name
                byte[] host_name = host.getBytes();

                final ByteArrayOutputStream baos = new ByteArrayOutputStream();
                final DataOutputStream dos = new DataOutputStream(baos);
                dos.writeShort(host_name.length + 3); // entry size
                dos.writeByte(0); // name type = hostname
                dos.writeShort(host_name.length);
                dos.write(host_name);
                dos.close();
                clientExtensions.put(ExtensionType.server_name, baos.toByteArray());
                return clientExtensions;
            }

            @Override
            public TlsAuthentication getAuthentication()
                    throws IOException {
                return new TlsAuthentication() {

                    @Override
                    public void notifyServerCertificate(Certificate serverCertificate) throws IOException {

                        try {

                            CertificateFactory cf = CertificateFactory.getInstance("X.509");

                            InputStream is = new FileInputStream("c:/ascert/test-tls.cer"); //"c:/cert/test-tls.cer");
                            InputStream caInput = new BufferedInputStream(is);
                            java.security.cert.Certificate ca;
                            try {
                                ca = cf.generateCertificate(caInput);
                                System.out.println("ca=" + ((java.security.cert.X509Certificate) ca).getSubjectDN());
                            } finally {
                                caInput.close();
                            }

                            List<java.security.cert.Certificate> certs = new LinkedList<java.security.cert.Certificate>();
                            for (org.bouncycastle.asn1.x509.Certificate c : serverCertificate.getCertificateList()) {
                                certs.add(cf.generateCertificate(new ByteArrayInputStream(c.getEncoded())));
                                System.out.println(c.getIssuer());
                            }
                            peertCerts = certs.toArray(new java.security.cert.Certificate[0]);
                        } catch (Exception e) {
                            System.out.println("Failed to cache server certs" + e);
                            throw new IOException(e);
                        }

                    }

                    @Override
                    public TlsCredentials getClientCredentials(CertificateRequest arg0)
                            throws IOException {
                        return null;
                    }

                };

当我运行一个简单的例子时:

public class Test {
public static void main(String[] args)
{
   String url = "https://blagajne-test.fu.gov.si:9002/v1/cash_registers";
    try {
        URLConnection connection = new URL(url).openConnection();
        HttpsURLConnection httpsURLConnection = (HttpsURLConnection) connection;
        httpsURLConnection.setSSLSocketFactory(new TSLSocketConnectionFactory());
         int responseCode = httpsURLConnection.getResponseCode();

    } catch (MalformedURLException ex) {
        Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex) {
        Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
    }

}

我得到这个错误: 严重:空 org.bouncycaSTLe.crypto.tls.TlsFatalAlertReceived:handshake_failure(40) 在 org.bouncycaSTLe.crypto.tls.TlsProtocol.handleAlertMessage(未知来源)

我不知道如何正确编写 SSLSocketFactory 以使用证书对远程服务器进行身份验证。感谢您的帮助。

最佳答案

最新版本的 BouncyCaSTLe 在 bctls-jdk15on-159 jar 中包含一个 JSSE 提供程序(“BCJSSE”,在类 org.bouncycaSTLe.jsse.provider.BouncyCaSTLeJsseProvider 中)。如果您安装此提供程序的优先级高于默认提供程序,那么您的原始代码示例应自动选择 BCJSSE 提供程序。

BCJSSE 支持 TLS 1.2 回到 JDK 1.5。在 org.bouncycaSTLe.jsse 包中还有一些特定于 BCJSSE 的扩展,用于访问 SunJSSE 在早期 JDK 中(或根本不支持)不支持的 TLS 功能,例如服务器名称指示。

与 SunJSSE 相比,仍然缺少一些小功能,但对于大多数用户来说,它应该是一个直接的替代品,当然比自己实现 SSLSocketFactory 更好。

关于java - 将证书添加到 BouncyCaSTLe TLSSocketConnectionFactory,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49360233/

相关文章:

java - 如何保留调试参数名称?

java - 如何延迟 java 中 for 循环中的方法?

java - 如何加载椭圆曲线 PEM 编码的私钥?

java - 使用 Bouncy CaSTLe Java API 生成 X.509 证书

java - 使用充气城堡使用中间证书正确创建新证书

java - Android RSA key 对生成-我应该使用标准Java/Bouncy CaSTLe/海绵城堡/JSch/其他吗?

Java代码、ASCII艺术、switch语句/结构、输入字符然后将其打印在屏幕上

java - 如何使用 Java 在 KML 中标记多个坐标?

java - 为什么 int exp1 = 14/20*100;等于java中的 '0'吗?

c# - .NET ECDiffieHellmanCng与BouncyCaSTLe Core兼容协议(protocol)