ssl 如何在Java 6中使用TLS 1.2

czq61nw1  于 2022-11-14  发布在  Java
关注(0)|答案(9)|浏览(581)

Java 6似乎支持TLS v1.0,有没有办法在Java 6中使用TLS 1.2?
也许Java6的一个补丁或特定更新会支持它?

fquxozlt

fquxozlt1#

在使用了几个小时的Oracle JDK 1.6之后,我能够在不更改任何代码的情况下使其正常工作。Bouncy Castle的神奇之处在于处理SSL,并允许JDK 1.6在默认情况下与TLSv1.2一起运行。从理论上讲,它也可以应用于较旧的Java版本,但需要进行最终的调整。
1.从Java Archive Oracle website下载最新的Java 1.6版本
1.在首选路径上解压缩该文件,并设置JAVA_HOME环境变量
1.使用最新的Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 6更新JDK
1.下载Bounce Castle jar文件bcprov-jdk15to18-1.72.jarbctls-jdk15to18-1.72.jar,并将它们复制到您的${JAVA_HOME}/jre/lib/ext文件夹中
1.修改文件${JAVA_HOME}/jre/lib/security/java.security,注解掉providers部分并添加一些额外的行

# Original security providers (just comment it)
    # security.provider.1=sun.security.provider.Sun
    # security.provider.2=sun.security.rsa.SunRsaSign
    # security.provider.3=com.sun.net.ssl.internal.ssl.Provider
    # security.provider.4=com.sun.crypto.provider.SunJCE
    # security.provider.5=sun.security.jgss.SunProvider
    # security.provider.6=com.sun.security.sasl.Provider
    # security.provider.7=org.jcp.xml.dsig.internal.dom.XMLDSigRI
    # security.provider.8=sun.security.smartcardio.SunPCSC

    # Add the Bouncy Castle security providers with higher priority
    security.provider.1=org.bouncycastle.jce.provider.BouncyCastleProvider
    security.provider.2=org.bouncycastle.jsse.provider.BouncyCastleJsseProvider
    
    # Original security providers with different priorities
    security.provider.3=sun.security.provider.Sun
    security.provider.4=sun.security.rsa.SunRsaSign
    security.provider.5=com.sun.net.ssl.internal.ssl.Provider
    security.provider.6=com.sun.crypto.provider.SunJCE 
    security.provider.7=sun.security.jgss.SunProvider
    security.provider.8=com.sun.security.sasl.Provider
    security.provider.9=org.jcp.xml.dsig.internal.dom.XMLDSigRI
    security.provider.10=sun.security.smartcardio.SunPCSC

    # Here we are changing the default SSLSocketFactory implementation
    ssl.SocketFactory.provider=org.bouncycastle.jsse.provider.SSLSocketFactoryImpl

为了确保它能正常工作,让我们编写一个简单的Java程序,使用https从一个URL下载文件。

import java.io.*;
import java.net.*;

public class DownloadWithHttps {

    public static void main(String[] args) {
        try {
            URL url = new URL(args[0]);
            System.out.println("File to Download: " + url);
            String filename = url.getFile();
            File f = new File(filename);
            System.out.println("Output File: " + f.getName());
            BufferedInputStream in = new BufferedInputStream(url.openStream());
            FileOutputStream fileOutputStream = new FileOutputStream(f.getName());
            int bytesRead;
            byte dataBuffer[] = new byte[1024];

            while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
                fileOutputStream.write(dataBuffer, 0, bytesRead);
            }
            fileOutputStream.close();

        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }
}

现在,只需编译DownloadWithHttps.java程序并使用Java 1.6执行它

${JAVA_HOME}/bin/javac DownloadWithHttps.java
${JAVA_HOME}/bin/java DownloadWithHttps https://repo1.maven.org/maven2/org/apache/commons/commons-lang3/3.10/commons-lang3-3.10.jar

Windows使用者的重要注意事项:此解决方案已在Linux操作系统中测试,如果您使用的是Windows,请将${JAVA_HOME}替换为%JAVA_HOME%

sqyvllje

sqyvllje2#

Oracle Java 6的公共版本不支持TLSv1.2。Java 6的付费版本(停产后)可能支持。(UPDATE- TLSv1.1可用于更新111之后的Java 1.6;(第10页)
请与Oracle销售部门联系。
其他备选方案包括:

TLSv1.1和TLSv1.2仅适用于Java 6服务刷新10、Java 6.0.1服务刷新1(J 9 VM2.6)及更高版本。
然而,我建议升级到Java 11(现在)。Java 6在2013年2月就已经停产了,继续使用它有潜在的风险。免费的Oracle Java 8在许多用例中都已经停产了。(告诉或提醒老板/客户。他们需要知道。)

ryoqjall

ryoqjall3#

Java 6,现在支持TLS 1.2,请在下面查看
http://www.oracle.com/technetwork/java/javase/overview-156328.html#R160_121

bf1o4zei

bf1o4zei4#

此处是一个TLSConnection工厂:

package test.connection;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.Principal;
import java.security.SecureRandom;
import java.security.Security;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;

import javax.net.ssl.HandshakeCompletedEvent;
import javax.net.ssl.HandshakeCompletedListener;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSessionContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.security.cert.X509Certificate;

import org.bouncycastle.crypto.tls.Certificate;
import org.bouncycastle.crypto.tls.CertificateRequest;
import org.bouncycastle.crypto.tls.DefaultTlsClient;
import org.bouncycastle.crypto.tls.ExtensionType;
import org.bouncycastle.crypto.tls.TlsAuthentication;
import org.bouncycastle.crypto.tls.TlsClientProtocol;
import org.bouncycastle.crypto.tls.TlsCredentials;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

/**
 * This Class enables TLS V1.2  connection based on BouncyCastle Providers.
 * Just to use: 
 * URL myurl = new URL( "http:// ...URL tha only Works in TLS 1.2);
   HttpsURLConnection  con = (HttpsURLConnection )myurl.openConnection();
   con.setSSLSocketFactory(new TSLSocketConnectionFactory());  
 * @author AZIMUTS
 *
 */
public class TSLSocketConnectionFactory 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) { 

        }
    }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//SECURE RANDOM
/////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
    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() {
                // TODO Auto-generated method stub
                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 {
                        // TODO Auto-generated method stub
                        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

    }
}

请记住,要证明这一点,最好是针对仅公开TLS 1.2的网站进行测试。如果Web公开TLS 1.0,则TLS 1.1(取决于Java实现)将使用tls 1.0、tls 1.1进行连接。针对仅公开TLS 1.2的站点进行测试。例如NIST安全站点https://www.nist.gov

wbrvyc0a

wbrvyc0a5#

您必须基于Bouncy Castle创建自己的SSLSocketFactory,使用后传递给通用的HttpsConnextion来使用这个自定义的SocketFactory。

1.第一:创建一个TLSConnectionFactory

这里有一个提示:
1.1扩展SSL连接工厂
1.2覆写这个方法:

@Override 
public Socket createSocket(Socket socket, final String host, int port, boolean arg3)

此方法将调用下一个内部方法,
1.3实现一个内部方法_createSSLSocket(主机,tlsClientProtocol);
这里你必须创建一个使用TlsClientProtocol的套接字。

private SSLSocket _createSSLSocket(final String host , final TlsClientProtocol tlsClientProtocol) {
     return new SSLSocket() {    
       .... Override and implement SSLSocket methods,  particulary: 
            startHandshake() {
             }    
     }

重要提示:此处详细说明了如何使用TLS客户端协议的完整示例:Using BouncyCastle for a simple HTTPS query

2.第二次:在通用HTTPS连接上使用此自定义SSL连接工厂。

这是很重要的!在其他的例子中你可以看到网页,你看到硬编码的HTTP命令...所以有了一个自定义的SSLConnectionFactory你就不需要更多了...

URL myurl = new URL( "http:// ...URL tha only Works in TLS 1.2);
  HttpsURLConnection  con = (HttpsURLConnection )myurl.openConnection();
  con.setSSLSocketFactory(new TSLSocketConnectionFactory());
a9wyjsp7

a9wyjsp76#

如果你需要访问一组特定的远程服务,你可以使用一个中间的反向代理来为你执行tls1.2,这样你就保存再去打补丁或者升级java1.6了。
例如,应用程序-〉代理服务器:http(5500)[tls-1.2] -〉远程:https(443)
apache httpd最简单的配置形式(每个服务一个端口)是:

Listen 127.0.0.1:5000
<VirtualHost *:5500>
    SSLProxyEngine On
    ProxyPass / https://remote-domain/
    ProxyPassReverse / https://remote-domain/
</VirtualHost>

然后访问http://localhost:5500/,而不是访问https://remote-domain/

注:如果您无法更改service-client代码/config以使其面向localhost域,你可以一直使用hosts文件,并将远程域转换为代理的ip。但这有一个问题。反向代理需要将同一个域解析为原始服务的ip。你可以通过将代理移动到另一台机器上来实现这一点(没有主机文件条目)或通过dockerizing IT并利用--add-host特征(或docker-compose中的extra_hosts)。

wvmv3b1j

wvmv3b1j7#

我认为@Azimuts(https://stackoverflow.com/a/33375677/6503697)的解决方案只适用于HTTP连接。对于FTPS连接,您可以使用带有org.apache.commons.net.ftp.FTPSClient的Bouncy Castle,而无需重写FTPS协议。
我有一个程序在JRE 1.6.0_04上运行,但我无法更新JRE。
该程序必须连接到一个FTPS服务器,只与TLS 1.2(IIS服务器).
我挣扎了几天,最后我明白了在我的用例中有几个版本的充气城堡库:bctls-jdk15on-1.60.jar和bcprov-jdk15on-1.60.jar正常,但1.64版本不正常。
apache公用网的版本是3.1。
下面是一小段应该可以正常工作的代码:

import java.io.ByteArrayOutputStream;
import java.security.SecureRandom;
import java.security.Security;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.commons.net.ftp.FTPSClient;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider;
import org.junit.Test;

public class FtpsTest {

// 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(java.security.cert.X509Certificate[] certs, String authType) {
    }

    public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {
    }
} };

@Test public void test() throws Exception {

    Security.insertProviderAt(new BouncyCastleProvider(), 1);
    Security.addProvider(new BouncyCastleJsseProvider());

    SSLContext sslContext = SSLContext.getInstance("TLS", new BouncyCastleJsseProvider());
    sslContext.init(null, trustAllCerts, new SecureRandom());
    org.apache.commons.net.ftp.FTPSClient ftpClient = new FTPSClient(sslContext);
    ByteArrayOutputStream out = null;
    try {

        ftpClient.connect("hostaname", 21);
        if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
            String msg = "Il server ftp ha rifiutato la connessione.";
            throw new Exception(msg);
        }
        if (!ftpClient.login("username", "pwd")) {
            String msg = "Il server ftp ha rifiutato il login con username:  username  e pwd:  password  .";
            ftpClient.disconnect();
            throw new Exception(msg);
        }

        ftpClient.enterLocalPassiveMode();
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
        ftpClient.setDataTimeout(60000);
        ftpClient.execPBSZ(0); // Set protection buffer size
        ftpClient.execPROT("P"); // Set data channel protection to private
        int bufSize = 1024 * 1024; // 1MB
        ftpClient.setBufferSize(bufSize);
        out = new ByteArrayOutputStream(bufSize);
        ftpClient.retrieveFile("remoteFileName", out);
        out.toByteArray();
    }
    finally {
        if (out != null) {
            out.close();
        }
        ftpClient.disconnect();

    }

}

}

j9per5c4

j9per5c48#

当我被迫使用TLS1.2 for java 6时,我也遇到了类似的错误。多亏了这个库,我才得以处理:
1.复制源代码:https://github.com/tobszarny/ssl-provider-jvm16
1.添加主类:

public static void main(String[] args) throws Exception {
    try {
        String apiUrl = "https://domain/api/query?test=123";

        URL myurl = new URL(apiUrl);
        HttpsURLConnection con = (HttpsURLConnection) myurl.openConnection();
        con.setSSLSocketFactory(new TSLSocketConnectionFactory());
        int responseCode = con.getResponseCode();
        System.out.println("GET Response Code :: " + responseCode);
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}
wribegjk

wribegjk9#

另一个BouncyCastle示例。仅使用bcprov-jdk15to18bctls-jdk15to18bcutil-jdk15to18就完成了我们的旧1.6客户端应用程序的工作。UPDATE:BC版本1.71

public static void main(String[] args) throws Exception {

    //put BC providers in runtime context
    if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
        Security.insertProviderAt(new BouncyCastleProvider(), 1);
        Security.insertProviderAt(new BouncyCastleJsseProvider(), 2);
    }

    //create an empty trust manager
    TrustManager[] trustManager = new TrustManager[] { new X509TrustManager() {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
        public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {}
        public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {}
    } };

    //initialize SSLContext 
    SSLContext sslContext = SSLContext.getInstance("TLSv1.2");        
    sslContext.init(null, trustManager, new SecureRandom());
    
    //connect and print data
    URL url = new URL("https://stackoverflow.com");
    HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
    connection.setSSLSocketFactory(sslContext.getSocketFactory());        
    connection.setRequestMethod("GET");
    InputStream returnStream = connection.getInputStream();        
    for (int ch; (ch = returnStream.read()) != -1; ) {
        System.out.print((char) ch);
    }
    returnStream.close();
    connection.disconnect();
}

相关问题