2016-05-23 11 views
1

ich einen Android-App für API-Ebene entwickle 16+ und von dem, was ich von Standard TLS v1.1 und TLS v1.2 gesehen habe, werden unterstützt, aber nicht aktiviert auf Android 4.1+Android 4.2.2, Wie TLS 1.2 für HttpsURLConnection aktivieren?

Ich habe die SSLSocketFacory von hier verwendet :

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

die ich es geschafft haben, mit dem folgenden Beispiel zum Laufen zu bringen:

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; 
} 
} 

und ich bin mit dem folgenden nennen:

Ich kann für eine Socket-Verbindung sehen ich habe jetzt die richtigen aktivierten Protokolle, aber wie kann ich diese Protokolle für eine URL-Verbindung aktivieren? Wie würde ich auch überprüfen, dass diese Protokolle für die HttpsURLConnection aktiviert wurden?

Ich habe versucht, die SSL-Socket-Factory für die Verbindung zu setzen, aber ich bin nicht sicher, wie Sie überprüfen, dass die Protokolle aktiviert wurden?

UPDATE: Ich habe meinen Code wie folgt geändert:

    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(); 

Ich habe die folgende Implementierung des SSL-Fabrik verwendet

public class NoSSLv3SocketFactory erstreckt SSLSocketFactory { Privat letzte SSLSocketFactory Delegierter;

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); 
    } 
} 

}

aber ich erhalte die folgende Ausnahme:

javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL-Handshake abgebrochenen: ssl = 0xb838faa0: Fehler in SSL-Bibliothek, in der Regel ein Protokollfehler Fehler: 14077410: SSL-Routinen: SSL23_GET_SERVER_HELLO: SSLv3 Alarm Handshake-Fehler (extern/openssl/ssl/s23_clnt.c: 741 0x9da83901: 0x00000000)

Der SSL-Dienst hat nur TLSv1.2 enabl ed und SSLv3 wurde deaktiviert, aber App scheint immer noch mit sslv3?

Antwort

0

Ihr Code enthält bereits die Linie

HttpsURLConnection.setDefaultSSLSocketFactory(new TLSSocketFactory()); 

, die für alle Verbindungen in Ihrer Anwendung Ihre TLSSocketFactory setzt die danach festgelegt werden. Daher ist der Aufruf an connection.setSSLSocketFactory(new TLSSocketFactory()); redundant und sollte keine Wirkung haben.

Hinweis: Möglicherweise besteht ein Problem mit bereits geöffneten Verbindungen, die vor dem Aufruf setDefaultSSLSocketFactory hergestellt wurden und die intern zwischengespeichert und wiederverwendet werden. Daher wird empfohlen, die Standard-Socket-Factory zu setzen, bevor Sie eine Netzwerkverbindung öffnen.

0

UPDATE: Dies wurde nun das Problem behebt ein SSL-Zertifikat Problem war, und kann bestätigen, dass beide Methoden für Android api Ebene arbeiten 16+

0

ich dieses Problem in den http://blog.dev-area.net/2015/08/13/android-4-1-enable-tls-1-1-and-tls-1-2/ Artikeln bereitgestellt nach dem Hinweis gelöst mit wenige Änderungen.

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); 

Dies ist der Code des benutzerdefinierten TLSSocketFactory:

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; 
    } 
} 

Sie auch das Serverzertifikat mit Online-Diensten wie https://www.ssllabs.com/ssltest/analyze.html, dass der Server das Zertifikat muss sicher sein, überprüfen Sie ermöglicht werden