哪些密码套件启用SSL套接字?
我正在使用Java的SSLSocket来保护客户端和服务器程序之间的通信。 服务器程序还提供来自Web浏览器的HTTPS请求。
根据“ 使用Java开始encryption ”(第371页),您应该始终在您的SSLSocket
/ SSLServerSocket
上调用setEnabledCipherSuites
,以确保最终协商的密码套件对您的目的足够强大。
这就是说,调用我的SSLSocketFactory
的getDefaultCipherSuites
方法会产生大约180个选项。 这些选项的范围从TLS_RSA_WITH_AES_256_CBC_SHA
(我认为是相当安全的)到SSL_RSA_WITH_RC4_128_MD5
(不确定是否安全,给定MD5的当前状态)到SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
(不完全确定是什么)。
什么是密码套件的合理列表来限制套接字?
请注意,客户端和服务器可以访问Bouncy Castle服务提供商,并且他们可能会或可能不会安装无限的encryption策略文件。
不要在输出中使用任何东西。 这是由于对强密码学的出口限制而导致的恶意软件。
编辑:改为使用2009文档。
2009年NIST build议列出以下内容,包括TLS_RSA_WITH_AES_256_CBC_SHA(您提到):
TLS_RSA_WITH_NULL_SHA (除非您确定不需要任何隐私/机密性,否则不要使用此function)。
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
下面是我用来执行密码套件和协议的Java类。 在SSLSocketFactoryEx
之前,我在访问SSLSocket
时修改了属性。 堆栈溢出的Java人帮助它,所以很高兴能够发布在这里。
SSLSocketFactoryEx
更喜欢使用更强大的密码套件(如ECDHE
和DHE
),并且省略了脆弱和脆弱的密码套件(如RC4
和MD5
)。 当TLS 1.2 不可用时,必须启用四个RSA密钥传输密码才能与Google和Microsoft互操作。 他们是TLS_RSA_WITH_AES_256_CBC_SHA256
, TLS_RSA_WITH_AES_256_CBC_SHA
和两个朋友。 如果可能,您应该删除TLS_RSA_*
密钥传输scheme。
保持密码套件列表尽可能小。 如果您广告所有可用的密码(类似于Flaschen的列表),那么您的列表将是80+。 这在ClientHello
占用了160个字节,并且可能会导致一些设备失败,因为它们具有用于处理ClientHello
的小型,固定大小的缓冲区。 破损的电器包括F5和Ironport。
在实践中,一旦首选列表与Java支持的密码套件相交,下面的代码中的列表将被配对成10或15个密码套件。 例如,以下是准备连接或microsoft.com或google.com时使用无限制JCE策略的列表:
- 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
该列表省略了弱/受伤algorithm,如RC4和MD5。 如果启用,那么您很可能会收到来自浏览器的过时encryption警告 。
该列表将使用默认的JCE策略更小,因为策略会删除AES-256和其他一些策略。 我认为它的约7密码套房与限制政策。
SSLSocketFactoryEx
类还确保使用TLS 1.0和更高版本的协议。 Java 8之前的Java客户端禁用TLS 1.1和1.2。 SSLContext.getInstance("TLS")
也会偷偷在SSLv3
(甚至在Java 8中),所以必须采取措施将其删除。
最后,下面的类是TLS 1.3知道的,所以它应该在提供者使它们可用时工作。 *_CHACHA20_POLY1305
密码套件是可取的,因为它们比当前的一些套件快得多,并且它们具有更好的安全属性。 Google已经在服务器上推出了它。 我不确定Oracle何时会提供它们。 OpenSSL将为他们提供OpenSSL 1.0.2 1.1.0 。
你可以这样使用它:
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<String> aa = new ArrayList<String>(); 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<String> aa = new ArrayList<String>(); 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; }