Cómo usar TLS 1.2 en Java 6

Parece que Java 6 admite TLS hasta v1.0, ¿hay alguna forma de utilizar TLS 1.2 en Java 6?

¿Tal vez un parche o una actualización particular de Java 6 tendrá soporte para ello?

    Las versiones públicas de Oracle Java 6 no son compatibles con TLSv1.2. Las versiones pagadas de Java 6 (post-EOL) podrían. ( ACTUALIZACIÓN – TLSv1.1 está disponible para Java 1.6 a partir de la actualización 111 en adelante; fuente )

    Póngase en contacto con ventas de Oracle.

    Otras alternativas son:

    • Use una implementación alternativa de JCE como Bouncy Castle.

    • Utilice una IBM Java 6 … si está disponible para su plataforma. Según “SDK de IBM, las correcciones de Java Technology Edition mitigan la vulnerabilidad de seguridad de POODLE (CVE-2014-3566)” :

      “TLSv1.1 y TLSv1.2 están disponibles solo para actualización de servicio Java 6, actualización de servicio Java 6.0.1 1 (J9 VM2.6) y versiones posteriores”.


    Sin embargo, le aconsejo actualizar a Java 8. Java 6 fue EOL en febrero de 2013, y seguir utilizando es potencialmente riesgoso. (Dígale o recuérdele al jefe / al cliente. Necesitan saberlo).

    Aquí una Fábrica 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 getClientExtensions() throws IOException { Hashtable clientExtensions = super.getClientExtensions(); if (clientExtensions == null) { clientExtensions = new Hashtable(); } //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 certs = new LinkedList(); 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 } } 

    Recuerde que para demostrar que esto es así, lo mejor es probar en contra de un sitio web que expone SOLO TLS 1.2. Si la web expone TLS 1.0, TLS 1.1 dependiendo de la implementación de Java se conectará usando tls 1.0, tls 1.1. Pruébelo en un sitio que solo expone TLS 1.2. Un ejemplo puede ser el sitio seguro de NIST https://www.nist.gov

    Java 6, ahora es compatible con TLS 1.2, mira a continuación

    http://www.oracle.com/technetwork/java/javase/overview-156328.html#R160_121

    Debe crear su propia SSLSocketFactory basada en Bouncy Castle. Luego de usarlo, pase a HttpsConnextion común para usar este SocketFactory personalizado.

    1. Primero: Crea una TLSConnectionFactory

    Aquí uno consejos:

    1.1 Extienda SSLConnectionFactory

    1.2 Anula este método:

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

    Este método llamará al siguiente método interno,

    1.3 Implementar un método interno _createSSLSocket (host, tlsClientProtocol);

    Aquí debe crear un socket usando TlsClientProtocol. El truco es anular … el método startHandshake () llamando a TlsClientProtocol

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

    Importante: El ejemplo completo de cómo usar el Protocolo de cliente TLS está bien explicado aquí: Usar BouncyCastle para una consulta HTTPS simple

    2. Segundo: Use este SSLConnextionFactory personalizado en HTTPSConnection común.

    Esto es importante ! En otras muestras puedes ver en la web, puedes ver Comandos HTTP codificados … así que con una SSLConnectionFactory personalizada no necesitas nada más …

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