TLS版本1.2 Java1.6 BouncyCastle内部TLS错误

时间:2018-02-09 19:47:56

标签: java bouncycastle tls1.2

我们有用java 1.6编写的应用程序 我们开发了一个基于Bouncy Castle Libraries的定制TLSSocketConnection工厂(v.1.57)

这是TLSSocketConnection工厂的代码片段

/**
 * This Class enables TLS V1.2  connection based on BouncyCastle Providers.
 */
public class TLSSocketConnectionFactory extends SSLSocketFactory {

    // ******************Adding Custom BouncyCastleProvider*********************//

    static {
        if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null)
            Security.addProvider(new BouncyCastleProvider());
    }

    // ******************HANDSHAKE LISTENER*********************//

    public class TLSHandshakeListener implements HandshakeCompletedListener {
        @Override
        public void handshakeCompleted(HandshakeCompletedEvent event) {

        }
    }

    private SecureRandom _secureRandom = new SecureRandom();

    // ******************Adding Custom BouncyCastleProvider*********************//

    @Override
    public Socket createSocket(Socket socket, final String host, int port, boolean arg3) throws IOException {
        if (socket == null) {
            socket = new Socket();
        }
        if (!socket.isConnected()) {
            socket.connect(new InetSocketAddress(host, port));
        }

        final TlsClientProtocol tlsClientProtocol = new TlsClientProtocol(socket.getInputStream(), socket.getOutputStream(), _secureRandom);
        return _createSSLSocket(host, tlsClientProtocol);
    }

    // ******************SOCKET FACTORY  METHODS*********************//

    @Override
    public String[] getDefaultCipherSuites() {
        return null;
    }

    @Override
    public String[] getSupportedCipherSuites() {
        return null;
    }

    @Override
    public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
        return null;
    }

    @Override
    public Socket createSocket(InetAddress host, int port) throws IOException {
        return null;
    }

    @Override
    public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
        return null;
    }

    @Override
    public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
        return null;
    }

    // ******************SOCKET CREATION*********************//

    private SSLSocket _createSSLSocket(final String host, final TlsClientProtocol tlsClientProtocol) {
        return new SSLSocket() {
            private java.security.cert.Certificate[] peertCerts;

            @Override
            public InputStream getInputStream() throws IOException {
                return tlsClientProtocol.getInputStream();
            }

            @Override
            public OutputStream getOutputStream() throws IOException {
                return tlsClientProtocol.getOutputStream();
            }

            @Override
            public synchronized void close() throws IOException {
                tlsClientProtocol.close();
            }

            @Override
            public void addHandshakeCompletedListener(HandshakeCompletedListener arg0) {

            }

            @Override
            public boolean getEnableSessionCreation() {
                return false;
            }

            @Override
            public String[] getEnabledCipherSuites() {
                return null;
            }

            @Override
            public String[] getEnabledProtocols() {
                return null;
            }

            @Override
            public boolean getNeedClientAuth() {
                return false;
            }

            @Override
            public SSLSession getSession() {
                return new SSLSession() {

                    @Override
                    public int getApplicationBufferSize() {
                        return 0;
                    }

                    @Override
                    public String getCipherSuite() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public long getCreationTime() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public byte[] getId() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public long getLastAccessedTime() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public java.security.cert.Certificate[] getLocalCertificates() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public Principal getLocalPrincipal() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public int getPacketBufferSize() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public X509Certificate[] getPeerCertificateChain() throws SSLPeerUnverifiedException {
                        return null;
                    }

                    @Override
                    public java.security.cert.Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
                        return peertCerts;
                    }

                    @Override
                    public String getPeerHost() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public int getPeerPort() {
                        return 0;
                    }

                    @Override
                    public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
                        return null;
                        //throw new UnsupportedOperationException();
                    }

                    @Override
                    public String getProtocol() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public SSLSessionContext getSessionContext() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public Object getValue(String arg0) {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public String[] getValueNames() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public void invalidate() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public boolean isValid() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public void putValue(String arg0, Object arg1) {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public void removeValue(String arg0) {
                        throw new UnsupportedOperationException();
                    }
                };
            }

            @Override
            public String[] getSupportedProtocols() {
                return null;
            }

            @Override
            public boolean getUseClientMode() {
                return false;
            }

            @Override
            public boolean getWantClientAuth() {
                return false;
            }

            @Override
            public void removeHandshakeCompletedListener(HandshakeCompletedListener arg0) {
            }

            @Override
            public void setEnableSessionCreation(boolean arg0) {
            }

            @Override
            public void setEnabledCipherSuites(String[] arg0) {
            }

            @Override
            public void setEnabledProtocols(String[] arg0) {
            }

            @Override
            public void setNeedClientAuth(boolean arg0) {
            }

            @Override
            public void setUseClientMode(boolean arg0) {
            }

            @Override
            public void setWantClientAuth(boolean arg0) {
            }

            @Override
            public String[] getSupportedCipherSuites() {
                return null;
            }

            @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");
                                    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())));
                                    }
                                    peertCerts = certs.toArray(new java.security.cert.Certificate[0]);
                                } catch (CertificateException e) {
                                    System.out.println("Failed to cache server certs" + e);
                                    throw new IOException(e);
                                }
                            }

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

    }
}

我们使用它的方式

HttpClient httpclient = HttpClientBuilder.create().setDefaultRequestConfig(getRequestConfig()).setRedirectStrategy(new LaxRedirectStrategy()).setSSLSocketFactory(getSSLContext()).build();
        logger.info(httpclient.toString());
        HttpClientContext context = getHttpContext();

        HttpPost httppost = new HttpPost(urlString);
        HttpResponse httpResponse = httpclient.execute(httppost, context);

private RequestConfig getRequestConfig() {
        return RequestConfig.custom().setConnectTimeout(320 * 1000).setConnectionRequestTimeout(320 * 1000).setSocketTimeout(320 * 1000).build();
    }

    private SSLConnectionSocketFactory getSSLContext() throws Exception {
        return new SSLConnectionSocketFactory(new TLSSocketConnectionFactory(), new String[] { "TLSv1.2" }, null, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    }

这样我最终会在日志中收到错误

Exception: : java.io.IOException: Internal TLS error, this could be an attack
    at org.bouncycastle.crypto.tls.TlsProtocol.failWithError(Unknown Source) [:1.57.0]
    at org.bouncycastle.crypto.tls.TlsProtocol.safeReadRecord(Unknown Source) [:1.57.0]
    at org.bouncycastle.crypto.tls.TlsProtocol.readApplicationData(Unknown Source) [:1.57.0]
    at org.bouncycastle.crypto.tls.TlsInputStream.read(Unknown Source) [:1.57.0]
    at org.apache.http.impl.io.SessionInputBufferImpl.streamRead(SessionInputBufferImpl.java:136) [:4.3.3]

知道怎么解决吗?是由于LaxRedirectStrategy还是设置SSL套接字连接超时? 很难弄清楚如何处理这个问题。而是从哪里开始解决这个问题。

1 个答案:

答案 0 :(得分:1)

确定。要更新所有人,此问题已通过以下设置修复

  1. http://www.bouncycastle.org/latest_releases.html获取最新jar(bcprov-jdk15on-159.jar)
  2. 我用v 1.59替换了v1.57并解决了这个问题。

    1. private RequestConfig getRequestConfig(){         return RequestConfig.custom()。setSocketTimeout(320 * 1000).build();     }