2016-05-23 3 views
1

Je développe une application Android pour le niveau API 16+ et de ce que j'ai vu par défaut TLS V1.1 et TLS v1.2 sont pris en charge mais pas activé sur Android 4.1+Android 4.2.2, Comment activer TLS 1.2 pour HttpsURLConnection?

J'ai utilisé le SSLSocketFacory d'ici :

http://blog.dev-area.net/2015/08/13/android-4-1-enable-tls-1-1-and-tls-1-2/

que j'ai réussi à faire travailler avec l'exemple suivant:

public class TLSSocketFactory extends SSLSocketFactory { 

    private SSLSocketFactory internalSSLSocketFactory; 

    public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException { 
    SSLContext context = SSLContext.getInstance("TLS"); 
    context.init(null, null, null); 
    internalSSLSocketFactory = context.getSocketFactory(); 

} 

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

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

public Socket createSocket() throws IOException{ 
    return enableTLSOnSocket(internalSSLSocketFactory.createSocket()); 
} 

@Override 
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { 
    return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose)); 
} 

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

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

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

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

private Socket enableTLSOnSocket(Socket socket) { 
    if(socket != null && (socket instanceof SSLSocket)) { 
     ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"}); 
    } 
    return socket; 
} 
} 

et je suis en utilisant ce qui suit pour l'appeler:

public class MainActivity extends AppCompatActivity { 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    try{ 

     SSLContext context = SSLContext.getDefault(); 
     TLSSocketFactory factory = new TLSSocketFactory(); 
     SSLSocket socket = (SSLSocket)factory.createSocket(); 
     String[] protocols = socket.getSupportedProtocols(); 

     // this now has the correct protocols enabled for sockets 
     String[] enabled = socket.getEnabledProtocols(); 



     HttpsURLConnection.setDefaultSSLSocketFactory(new TLSSocketFactory()); 
     URL url = new URL("https://mysslsite/"); 
     HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); 
     connection.setSSLSocketFactory(new TLSSocketFactory()); 

     Log.i("", ""); 
    }catch(Exception ex){ 
     ex.printStackTrace(); 
    } 
    } 
} 

Je peux voir pour une connexion socket j'ai maintenant les protocoles activés corrects, mais comment puis-je activer ces protocoles pour une connexion url? comment puis-je également vérifier que ces protocoles ont été activés pour le HttpsURLConnection?

J'ai essayé de définir l'usine de socket ssl pour la connexion mais je ne suis pas sûr de la façon de vérifier que les protocoles ont été activés?

MISE À JOUR: J'ai modifié mon code comme suit:

    String myURL = "https://mysslservice"; 
        SSLContext sslcontext = SSLContext.getInstance("TLS"); 
        sslcontext.init(null, null, null); 
        SSLSocketFactory noSSLv3Factory = new NoSSLv3SocketFactory(sslcontext.getSocketFactory()); 
        HttpsURLConnection.setDefaultSSLSocketFactory(noSSLv3Factory); 

        URL url = new URL(myURL); 

        HttpsURLConnection l_connection = (HttpsURLConnection) url.openConnection(); 
        l_connection.connect(); 

J'ai utilisé la mise en œuvre suivante de l'usine SSL

public class NoSSLv3SocketFactory étend SSLSocketFactory { délégué finale privée SSLSocketFactory;

public NoSSLv3SocketFactory() { 
    this.delegate = HttpsURLConnection.getDefaultSSLSocketFactory(); 
} 

public NoSSLv3SocketFactory(SSLSocketFactory delegate) { 
    this.delegate = delegate; 
} 

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

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

private Socket makeSocketSafe(Socket socket) { 
    if (socket instanceof SSLSocket) { 
     socket = new NoSSLv3SSLSocket((SSLSocket) socket); 
    } 
    return socket; 
} 

@Override 
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { 
    return makeSocketSafe(delegate.createSocket(s, host, port, autoClose)); 
} 

@Override 
public Socket createSocket(String host, int port) throws IOException { 
    return makeSocketSafe(delegate.createSocket(host, port)); 
} 

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

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

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

private class NoSSLv3SSLSocket extends DelegateSSLSocket { 

    private NoSSLv3SSLSocket(SSLSocket delegate) { 
     super(delegate); 

    } 

    @Override 
    public void setEnabledProtocols(String[] protocols) { 
     if (protocols != null && protocols.length == 1 && "SSLv3".equals(protocols[0])) { 

      List<String> enabledProtocols = new ArrayList<String>(Arrays.asList(delegate.getSupportedProtocols())); 
      if (enabledProtocols.size() > 1) { 
       enabledProtocols.remove("SSLv3"); 
       System.out.println("Removed SSLv3 from enabled protocols"); 
      } else { 
       System.out.println("SSL stuck with protocol available for " + String.valueOf(enabledProtocols)); 
      } 
      protocols = enabledProtocols.toArray(new String[enabledProtocols.size()]); 
     } 

     super.setEnabledProtocols(protocols); 
    } 
} 

public class DelegateSSLSocket extends SSLSocket { 

    protected final SSLSocket delegate; 

    DelegateSSLSocket(SSLSocket delegate) { 
     this.delegate = delegate; 
    } 

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

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

    @Override 
    public void setEnabledCipherSuites(String[] suites) { 
     delegate.setEnabledCipherSuites(suites); 
    } 

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

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

    @Override 
    public void setEnabledProtocols(String[] protocols) { 
     delegate.setEnabledProtocols(protocols); 
    } 

    @Override 
    public SSLSession getSession() { 
     return delegate.getSession(); 
    } 

    @Override 
    public void addHandshakeCompletedListener(HandshakeCompletedListener listener) { 
     delegate.addHandshakeCompletedListener(listener); 
    } 

    @Override 
    public void removeHandshakeCompletedListener(HandshakeCompletedListener listener) { 
     delegate.removeHandshakeCompletedListener(listener); 
    } 

    @Override 
    public void startHandshake() throws IOException { 
     delegate.startHandshake(); 
    } 

    @Override 
    public void setUseClientMode(boolean mode) { 
     delegate.setUseClientMode(mode); 
    } 

    @Override 
    public boolean getUseClientMode() { 
     return delegate.getUseClientMode(); 
    } 

    @Override 
    public void setNeedClientAuth(boolean need) { 
     delegate.setNeedClientAuth(need); 
    } 

    @Override 
    public void setWantClientAuth(boolean want) { 
     delegate.setWantClientAuth(want); 
    } 

    @Override 
    public boolean getNeedClientAuth() { 
     return delegate.getNeedClientAuth(); 
    } 

    @Override 
    public boolean getWantClientAuth() { 
     return delegate.getWantClientAuth(); 
    } 

    @Override 
    public void setEnableSessionCreation(boolean flag) { 
     delegate.setEnableSessionCreation(flag); 
    } 

    @Override 
    public boolean getEnableSessionCreation() { 
     return delegate.getEnableSessionCreation(); 
    } 

    @Override 
    public void bind(SocketAddress localAddr) throws IOException { 
     delegate.bind(localAddr); 
    } 

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

    @Override 
    public void connect(SocketAddress remoteAddr) throws IOException { 
     delegate.connect(remoteAddr); 
    } 

    @Override 
    public void connect(SocketAddress remoteAddr, int timeout) throws IOException { 
     delegate.connect(remoteAddr, timeout); 
    } 

    @Override 
    public SocketChannel getChannel() { 
     return delegate.getChannel(); 
    } 

    @Override 
    public InetAddress getInetAddress() { 
     return delegate.getInetAddress(); 
    } 

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

    @Override 
    public boolean getKeepAlive() throws SocketException { 
     return delegate.getKeepAlive(); 
    } 

    @Override 
    public InetAddress getLocalAddress() { 
     return delegate.getLocalAddress(); 
    } 

    @Override 
    public int getLocalPort() { 
     return delegate.getLocalPort(); 
    } 

    @Override 
    public SocketAddress getLocalSocketAddress() { 
     return delegate.getLocalSocketAddress(); 
    } 

    @Override 
    public boolean getOOBInline() throws SocketException { 
     return delegate.getOOBInline(); 
    } 

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

    @Override 
    public int getPort() { 
     return delegate.getPort(); 
    } 

    @Override 
    public synchronized int getReceiveBufferSize() throws SocketException { 
     return delegate.getReceiveBufferSize(); 
    } 

    @Override 
    public SocketAddress getRemoteSocketAddress() { 
     return delegate.getRemoteSocketAddress(); 
    } 

    @Override 
    public boolean getReuseAddress() throws SocketException { 
     return delegate.getReuseAddress(); 
    } 

    @Override 
    public synchronized int getSendBufferSize() throws SocketException { 
     return delegate.getSendBufferSize(); 
    } 

    @Override 
    public int getSoLinger() throws SocketException { 
     return delegate.getSoLinger(); 
    } 

    @Override 
    public synchronized int getSoTimeout() throws SocketException { 
     return delegate.getSoTimeout(); 
    } 

    @Override 
    public boolean getTcpNoDelay() throws SocketException { 
     return delegate.getTcpNoDelay(); 
    } 

    @Override 
    public int getTrafficClass() throws SocketException { 
     return delegate.getTrafficClass(); 
    } 

    @Override 
    public boolean isBound() { 
     return delegate.isBound(); 
    } 

    @Override 
    public boolean isClosed() { 
     return delegate.isClosed(); 
    } 

    @Override 
    public boolean isConnected() { 
     return delegate.isConnected(); 
    } 

    @Override 
    public boolean isInputShutdown() { 
     return delegate.isInputShutdown(); 
    } 

    @Override 
    public boolean isOutputShutdown() { 
     return delegate.isOutputShutdown(); 
    } 

    @Override 
    public void sendUrgentData(int value) throws IOException { 
     delegate.sendUrgentData(value); 
    } 

    @Override 
    public void setKeepAlive(boolean keepAlive) throws SocketException { 
     delegate.setKeepAlive(keepAlive); 
    } 

    @Override 
    public void setOOBInline(boolean oobinline) throws SocketException { 
     delegate.setOOBInline(oobinline); 
    } 

    @Override 
    public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) { 
     delegate.setPerformancePreferences(connectionTime, latency, bandwidth); 
    } 

    @Override 
    public synchronized void setReceiveBufferSize(int size) throws SocketException { 
     delegate.setReceiveBufferSize(size); 
    } 

    @Override 
    public void setReuseAddress(boolean reuse) throws SocketException { 
     delegate.setReuseAddress(reuse); 
    } 

    @Override 
    public synchronized void setSendBufferSize(int size) throws SocketException { 
     delegate.setSendBufferSize(size); 
    } 

    @Override 
    public void setSoLinger(boolean on, int timeout) throws SocketException { 
     delegate.setSoLinger(on, timeout); 
    } 

    @Override 
    public synchronized void setSoTimeout(int timeout) throws SocketException { 
     delegate.setSoTimeout(timeout); 
    } 

    @Override 
    public void setTcpNoDelay(boolean on) throws SocketException { 
     delegate.setTcpNoDelay(on); 
    } 

    @Override 
    public void setTrafficClass(int value) throws SocketException { 
     delegate.setTrafficClass(value); 
    } 

    @Override 
    public void shutdownInput() throws IOException { 
     delegate.shutdownInput(); 
    } 

    @Override 
    public void shutdownOutput() throws IOException { 
     delegate.shutdownOutput(); 
    } 

    @Override 
    public String toString() { 
     return delegate.toString(); 
    } 

    @Override 
    public boolean equals(Object o) { 
     return delegate.equals(o); 
    } 
} 

}

mais je reçois l'exception suivante:

javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: poignée de main SSL avorté: ssl = 0xb838faa0: échec dans bibliothèque SSL, généralement une erreur de protocole erreur: 14077410: routines SSL: SSL23_GET_SERVER_HELLO: échec de négociation alerte SSLv3 (externe/OpenSSL/ssl/s23_clnt.c: 741 0x9da83901: 0x00000000)

Le service SSL a seulement TLSv1.2 ENABL ed et SSLv3 a été désactivé, mais l'application semble toujours utiliser sslv3?

Répondre

0

Votre code contient déjà la ligne

HttpsURLConnection.setDefaultSSLSocketFactory(new TLSSocketFactory()); 

qui définit votre TLSSocketFactory pour toutes les connexions dans votre application qui sont établies par la suite. Par conséquent, l'appel à connection.setSSLSocketFactory(new TLSSocketFactory()); est redondant et ne devrait avoir aucun effet.

Remarque: Il se peut qu'il y ait un problème avec les connexions déjà ouvertes qui ont été établies avant l'appel setDefaultSSLSocketFactory et qui sont mises en cache en interne et réutilisées. Par conséquent, il est recommandé de définir la fabrique de connecteurs par défaut avant d'ouvrir une connexion réseau.

0

MISE À JOUR: Cela a été résolu le problème était un problème de certificat SSL et peut confirmer que les deux méthodes fonctionnent pour le niveau android api 16+

0

Je résolu cette question en suivant les indications fournies dans l'article http://blog.dev-area.net/2015/08/13/android-4-1-enable-tls-1-1-and-tls-1-2/ avec quelques changements.

SSLContext context = SSLContext.getInstance("TLS"); 
context.init(null, null, null); 
SSLSocketFactory noSSLv3Factory = null; 
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) { 
    noSSLv3Factory = new TLSSocketFactory(sslContext.getSocketFactory()); 
} else { 
    noSSLv3Factory = sslContext.getSocketFactory(); 
} 
connection.setSSLSocketFactory(noSSLv3Factory); 

C'est le code du TLSSocketFactory personnalisé:

public static class TLSSocketFactory extends SSLSocketFactory { 

    private SSLSocketFactory internalSSLSocketFactory; 

    public TLSSocketFactory(SSLSocketFactory delegate) throws KeyManagementException, NoSuchAlgorithmException { 
     internalSSLSocketFactory = delegate; 
    } 

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

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

    @Override 
    public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { 
     return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose)); 
    } 

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

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

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

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

    /* 
    * Utility methods 
    */ 

    private static Socket enableTLSOnSocket(Socket socket) { 
     if (socket != null && (socket instanceof SSLSocket) 
       && isTLSServerEnabled((SSLSocket) socket)) { // skip the fix if server doesn't provide the TLS version 
      ((SSLSocket) socket).setEnabledProtocols(new String[]{TLS_v1_1, TLS_v1_2}); 
     } 
     return socket; 
    } 

    private static boolean isTLSServerEnabled(SSLSocket sslSocket) { 
     System.out.println("__prova__ :: " + sslSocket.getSupportedProtocols().toString()); 
     for (String protocol : sslSocket.getSupportedProtocols()) { 
      if (protocol.equals(TLS_v1_1) || protocol.equals(TLS_v1_2)) { 
       return true; 
      } 
     } 
     return false; 
    } 
} 

Vous pouvez également vérifier le certificat de serveur à l'aide des services en ligne comme https://www.ssllabs.com/ssltest/analyze.html pour être sûr que le serveur a le certificat que vous activez