代码之家  ›  专栏  ›  技术社区  ›  Zarkonnen

要为SSL套接字启用哪些密码套件?

  •  20
  • Zarkonnen  · 技术社区  · 15 年前

    我使用Java的SSLSOCK来保护客户端和服务器程序之间的通信。服务器程序还提供来自Web浏览器的HTTPS请求。

    根据“ Beginning Cryptography with Java “,第371页,您应该随时拨打 setEnabledCipherSuites 对你 SSLSocket / SSLServerSocket 以确保最终谈判的密码套件对于您的目的足够强大。

    也就是说,打电话给我 SSLSocketFactory getDefaultCipherSuites 方法生成一些 一百八十 选项。这些选项的范围从 TLS_RSA_WITH_AES_256_CBC_SHA (我认为这是相当安全的)去 SSL_RSA_WITH_RC4_128_MD5 (不太确定这是否安全,考虑到MD5的当前状态)到 SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA (不完全确定这是怎么回事)。

    限制套接字的密码套件的合理列表是什么?

    请注意,客户端和服务器可以访问 Bouncy Castle 服务提供者,并且他们可能安装了或可能没有安装无限的加密策略文件。

    2 回复  |  直到 9 年前
        1
  •  7
  •   Matthew Flaschen    11 年前

    不要在里面使用任何有出口的东西。这是由于对强大密码技术的出口限制而造成的严重后果。

    编辑:更改为使用2009文档。

    2009个NIST recommendation 列出以下内容,包括tls_rsa_和aes_256_cbc_sha(您提到的):

    tls_rsa_with_null_sha (除非您确定不需要任何隐私/保密,否则不要使用此功能)。

    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 
    
        2
  •  16
  •   Community Egal    7 年前

    下面是我用来执行密码套件和协议的Java类。之前 SSLSocketFactoryEx ,我正在修改 SSLSocket 当我接触到他们的时候。堆栈溢出的Java成员帮助了它,因此能够在这里发布它是很好的。

    sslsocketfactoryex公司 更喜欢更强大的密码套件(比如 ECDHE DHE 它省略了脆弱和受伤的密码套件(比如 RC4 MD5 )当tls 1.2为 可用。他们是 TLS_RSA_WITH_AES_256_CBC_SHA256 , TLS_RSA_WITH_AES_256_CBC_SHA 还有两个朋友。如果可能,您应该删除 TLS_RSA_* 关键运输方案。

    尽可能少地保存密码套件列表。如果你做广告 全部的 可用密码(类似于flaschen的列表),那么您的列表将是80+。在 ClientHello 并且它可能会导致一些设备失败,因为它们有一个小的、固定大小的缓冲区来处理 克里斯蒂诺 . 损坏的电器包括F5和Ironport。

    实际上,一旦首选列表与Java支持的密码套件相交,下面代码中的列表就被配对到10或15个密码套件中。例如,以下是我在准备连接或Microsoft.com或Google.com时得到的列表,其中有一个不受限制的JCE策略:

    • 带aes的tls-ecdhe-ecdsa_-aes_-256_-cbc_-sha384
    • 带aes的tls-ecdhe-rsa-u-sha384
    • 带aes的tls-ecdhe-ecdsa_-aes_128_-cbc_sha256
    • 带AES的tls-ecdhe-rsa-u-sha256
    • Tls-Ecdhe-RSA-U,带AES-256-GCM-Sha384
    • 带aes的tls-dhe-dss-u-sha384
    • tls eu ecdhe_rsa_with_aes_128_gcm_sha256
    • Tsl-Dhe-DSS-U,带AES-128-GCM-Sha256
    • 带aes的tls-dhe-dss-u-sha256
    • Tls-Dhe-RSA-U,带AES-128-U CBC-Sha
    • Tsl-dhe-dss-u,带aes-128-cbc-sha
    • 带aes的tls rsa__256_cbc_sha256
    • 带aes的tls rsa__256_cbc_sha
    • tls_rsa_with_aes_128_cbc_sha256
    • 带aes的tls-rsa-u-sha

    该列表省略了弱/受伤算法,如rc4和md5。如果它们被启用,那么您可能会得到 Obsolete cryptography warning from Browser 有时。

    使用默认的JCE策略,列表将更小,因为该策略删除了AES-256和其他一些策略。我想大概有7套密码套装有限制政策。

    这个 sslsocketfactoryex公司 类还确保使用协议tls 1.0及更高版本。Java客户端在Java 8之前禁用TLS 1.1和1.2。 SSLContext.getInstance("TLS") 也会潜入 SSLv3 (即使在Java 8中),也必须采取措施来移除它。

    最后,下面的类是TLS 1.3感知的,因此当提供程序使它们可用时,它应该可以工作。这个 *_CHACHA20_POLY1305 如果可用,则首选密码套件,因为它们比某些当前套件快得多,并且具有更好的安全属性。谷歌已经在其服务器上推出了它。我不确定甲骨文什么时候提供。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;
    }