Quali suite di crittografia abilitare per SSL Socket?

Sto usando SSLSocket di Java per proteggere le comunicazioni tra un client e un programma server. Il programma server serve anche richieste HTTPS dai browser web.

Secondo ” Beginning Cryptography with Java “, pagina 371, dovresti sempre chiamare setEnabledCipherSuites sul tuo SSLSocket / SSLServerSocket per assicurarti che la suite di cifratura che finisce per essere negoziata sia sufficientemente forte per i tuoi scopi.

Detto questo, una chiamata al metodo SSLSocketFactory mio SSLSocketFactory produce circa 180 opzioni. Queste opzioni vanno da TLS_RSA_WITH_AES_256_CBC_SHA (che credo sia abbastanza sicuro) a SSL_RSA_WITH_RC4_128_MD5 (non sono sicuro se ciò è sicuro, dato lo stato attuale di MD5) a SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA (non del tutto sicuro di quello che fa).

Qual è un elenco ragionevole di suite di crittografia per limitare le prese?

Si noti che il client e il server hanno accesso al provider del servizio Bouncy Castle e che possono o non possono avere file di criteri di crittografia illimitati installati.

Non usare nulla con l’esportazione in esso. Questo è crippleware a causa delle restrizioni alle esportazioni sulla crittografia forte.

EDIT: modificato per utilizzare il documento 2009.

Una raccomandazione NIST 2009 elenca i seguenti, inclusivi TLS_RSA_WITH_AES_256_CBC_SHA (che hai menzionato):

TLS_RSA_WITH_NULL_SHA (non usare questo a meno che tu non sia sicuro di non aver bisogno di alcuna privacy / riservatezza).

 TLS_RSA_WITH_3DES_EDE_CBC_SHA TLS_RSA_WITH_AES_128_CBC_SHA TLS_RSA_WITH_AES_256_CBC_SHA TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA TLS_DH_DSS_WITH_AES_128_CBC_SHA TLS_DH_RSA_WITH_AES_128_CBC_SHA TLS_DHE_DSS_WITH_AES_128_CBC_SHA TLS_DHE_RSA_WITH_AES_128_CBC_SHA TLS_DH_DSS_WITH_AES_256_CBC_SHA TLS_DH_RSA_WITH_AES_256_CBC_SHA TLS_DHE_DSS_WITH_AES_256_CBC_SHA TLS_DHE_RSA_WITH_AES_256_CBC_SHA TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA TLS_ECDH_RSA_WITH_AES_128_CBC_SHA TLS_ECDH_RSA_WITH_AES_256_CBC_SHA TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA TLS_PSK_WITH_3DES_EDE_CBC_SHA TLS_PSK_WITH_AES_128_CBC_SHA TLS_PSK_WITH_AES_256_CBC_SHA TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA TLS_DHE_PSK_WITH_AES_128_CBC_SHA TLS_DHE_PSK_WITH_AES_256_CBC_SHA TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA TLS_RSA_PSK_WITH_AES_128_CBC_SHA TLS_RSA_PSK_WITH_AES_256_CBC_SHA TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 

Di seguito è riportata la class Java che utilizzo per applicare suite di crittografia e protocolli. Prima di SSLSocketFactoryEx , stavo modificando le proprietà su SSLSocket quando ho avuto accesso ad esse. La gente di Java su Stack Overflow ci ha aiutato, quindi è bello poterlo postare qui.

SSLSocketFactoryEx preferisce suite di crittografia più potenti (come ECDHE e DHE ) e omette suite di crittografia deboli e ferite (come RC4 e MD5 ). È necessario abilitare quattro crittografie per il trasporto di chiavi RSA per l’interoperabilità con Google e Microsoft quando TLS 1.2 non è disponibile. Sono TLS_RSA_WITH_AES_256_CBC_SHA256 , TLS_RSA_WITH_AES_256_CBC_SHA e due amici. Se ansible, è necessario rimuovere gli schemi di trasporto delle chiavi TLS_RSA_* .

Mantenere la lista delle suite di cifratura il più piccola ansible. Se fai pubblicità a tutti i cipher disponibili (simile alla lista di Flaschen), allora la tua lista sarà 80+. Ciò richiede 160 byte in ClientHello e può causare il malfunzionamento di alcune appliance, poiché dispongono di un buffer di dimensioni ridotte per l’elaborazione di ClientHello . Gli apparecchi rotti includono F5 e Ironport.

In pratica, l’elenco nel codice sottostante è abbinato a 10 o 15 pacchetti di crittografia una volta che l’elenco preferito si interseca con le suite di crittografia supportate di Java. Ad esempio, ecco l’elenco che ottengo quando mi preparo per connettermi o microsoft.com o google.com con una politica JCE illimitata in atto:

  • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  • TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  • TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
  • TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
  • TLS_DHE_RSA_WITH_AES_128_CBC_SHA
  • TLS_DHE_DSS_WITH_AES_128_CBC_SHA
  • TLS_RSA_WITH_AES_256_CBC_SHA256
  • TLS_RSA_WITH_AES_256_CBC_SHA
  • TLS_RSA_WITH_AES_128_CBC_SHA256
  • TLS_RSA_WITH_AES_128_CBC_SHA

L’elenco omette gli algoritmi deboli / feriti, come RC4 e MD5. Se sono abilitati, in alcuni casi è probabile che venga visualizzato un avviso di crittografia obsoleto dal browser .

L’elenco sarà più piccolo con il criterio JCE predefinito poiché il criterio rimuove AES-256 e alcuni altri. Penso che sia circa 7 suite di crittografia con la politica limitata.

La class SSLSocketFactoryEx garantisce inoltre i protocolli TLS 1.0 e successivi. I client Java precedenti a Java 8 disabilitano TLS 1.1 e 1.2. SSLContext.getInstance("TLS") si SSLContext.getInstance("TLS") in SSLv3 (anche in Java 8), quindi è necessario prendere provvedimenti per rimuoverlo.

Infine, la class di seguito è TLS 1.3, quindi dovrebbe funzionare quando il provider li rende disponibili. Le suite di crittografia *_CHACHA20_POLY1305 sono preferibili se disponibili perché sono molto più veloci di alcune delle suite attuali e hanno proprietà di sicurezza migliori. Google lo ha già implementato sui suoi server. Non sono sicuro di quando Oracle fornirà loro. OpenSSL fornirà loro OpenSSL 1.0.2 1.1.0 .

Puoi usarlo in questo modo:

 URL url = new URL("https://www.google.com:443"); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); SSLSocketFactoryEx factory = new SSLSocketFactoryEx(); connection.setSSLSocketFactory(factory); connection.setRequestProperty("charset", "utf-8"); InputStream input = connection.getInputStream(); InputStreamReader reader = new InputStreamReader(input, "utf-8"); BufferedReader buffer = new BufferedReader(reader); ... 

 class SSLSocketFactoryEx extends SSLSocketFactory { public SSLSocketFactoryEx() throws NoSuchAlgorithmException, KeyManagementException { initSSLSocketFactoryEx(null,null,null); } public SSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random) throws NoSuchAlgorithmException, KeyManagementException { initSSLSocketFactoryEx(km, tm, random); } public SSLSocketFactoryEx(SSLContext ctx) throws NoSuchAlgorithmException, KeyManagementException { initSSLSocketFactoryEx(ctx); } public String[] getDefaultCipherSuites() { return m_ciphers; } public String[] getSupportedCipherSuites() { return m_ciphers; } public String[] getDefaultProtocols() { return m_protocols; } public String[] getSupportedProtocols() { return m_protocols; } public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { SSLSocketFactory factory = m_ctx.getSocketFactory(); SSLSocket ss = (SSLSocket)factory.createSocket(s, host, port, autoClose); ss.setEnabledProtocols(m_protocols); ss.setEnabledCipherSuites(m_ciphers); return ss; } public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { SSLSocketFactory factory = m_ctx.getSocketFactory(); SSLSocket ss = (SSLSocket)factory.createSocket(address, port, localAddress, localPort); ss.setEnabledProtocols(m_protocols); ss.setEnabledCipherSuites(m_ciphers); return ss; } public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException { SSLSocketFactory factory = m_ctx.getSocketFactory(); SSLSocket ss = (SSLSocket)factory.createSocket(host, port, localHost, localPort); ss.setEnabledProtocols(m_protocols); ss.setEnabledCipherSuites(m_ciphers); return ss; } public Socket createSocket(InetAddress host, int port) throws IOException { SSLSocketFactory factory = m_ctx.getSocketFactory(); SSLSocket ss = (SSLSocket)factory.createSocket(host, port); ss.setEnabledProtocols(m_protocols); ss.setEnabledCipherSuites(m_ciphers); return ss; } public Socket createSocket(String host, int port) throws IOException { SSLSocketFactory factory = m_ctx.getSocketFactory(); SSLSocket ss = (SSLSocket)factory.createSocket(host, port); ss.setEnabledProtocols(m_protocols); ss.setEnabledCipherSuites(m_ciphers); return ss; } private void initSSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random) throws NoSuchAlgorithmException, KeyManagementException { m_ctx = SSLContext.getInstance("TLS"); m_ctx.init(km, tm, random); m_protocols = GetProtocolList(); m_ciphers = GetCipherList(); } private void initSSLSocketFactoryEx(SSLContext ctx) throws NoSuchAlgorithmException, KeyManagementException { m_ctx = ctx; m_protocols = GetProtocolList(); m_ciphers = GetCipherList(); } protected String[] GetProtocolList() { String[] preferredProtocols = { "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3" }; String[] availableProtocols = null; SSLSocket socket = null; try { SSLSocketFactory factory = m_ctx.getSocketFactory(); socket = (SSLSocket)factory.createSocket(); availableProtocols = socket.getSupportedProtocols(); Arrays.sort(availableProtocols); } catch(Exception e) { return new String[]{ "TLSv1" }; } finally { if(socket != null) socket.close(); } List aa = new ArrayList(); for(int i = 0; i < preferredProtocols.length; i++) { int idx = Arrays.binarySearch(availableProtocols, preferredProtocols[i]); if(idx >= 0) aa.add(preferredProtocols[i]); } return aa.toArray(new String[0]); } protected String[] GetCipherList() { String[] preferredCiphers = { // *_CHACHA20_POLY1305 are 3x to 4x faster than existing cipher suites. // http://googleonlinesecurity.blogspot.com/2014/04/speeding-up-and-strengthening-https.html // Use them if available. Normative names can be found at (TLS spec depends on IPSec spec): // http://tools.ietf.org/html/draft-nir-ipsecme-chacha20-poly1305-01 // http://tools.ietf.org/html/draft-mavrogiannopoulos-chacha-tls-02 "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_ECDSA_WITH_CHACHA20_SHA", "TLS_ECDHE_RSA_WITH_CHACHA20_SHA", "TLS_DHE_RSA_WITH_CHACHA20_POLY1305", "TLS_RSA_WITH_CHACHA20_POLY1305", "TLS_DHE_RSA_WITH_CHACHA20_SHA", "TLS_RSA_WITH_CHACHA20_SHA", // Done with bleeding edge, back to TLS v1.2 and below "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", // TLS v1.0 (with some SSLv3 interop) "TLS_DHE_RSA_WITH_AES_256_CBC_SHA384", "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA", "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA", "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA", "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA", // RSA key transport sucks, but they are needed as a fallback. // For example, microsoft.com fails under all versions of TLS // if they are not included. If only TLS 1.0 is available at // the client, then google.com will fail too. TLS v1.3 is // trying to deprecate them, so it will be interesteng to see // what happens. "TLS_RSA_WITH_AES_256_CBC_SHA256", "TLS_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA" }; String[] availableCiphers = null; try { SSLSocketFactory factory = m_ctx.getSocketFactory(); availableCiphers = factory.getSupportedCipherSuites(); Arrays.sort(availableCiphers); } catch(Exception e) { return new String[] { "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", "TLS_DHE_DSS_WITH_AES_256_CBC_SHA", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_256_CBC_SHA256", "TLS_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_EMPTY_RENEGOTIATION_INFO_SCSV" }; } List aa = new ArrayList(); for(int i = 0; i < preferredCiphers.length; i++) { int idx = Arrays.binarySearch(availableCiphers, preferredCiphers[i]); if(idx >= 0) aa.add(preferredCiphers[i]); } aa.add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV"); return aa.toArray(new String[0]); } private SSLContext m_ctx; private String[] m_ciphers; private String[] m_protocols; }