gpt4 book ai didi

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

转载 作者:IT老高 更新时间:2023-10-28 20:47:08 25 4
gpt4 key购买 nike

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

根据“Beginning Cryptography with Java”,第 371 页,您应该始终在您的 SSLSocket/SSLServerSocket 上调用 setEnabledCipherSuites 以确保密码最终协商的套件对于您的目的来说足够强大。

话虽如此,调用我的 SSLSocketFactorygetDefaultCipherSuites 方法会产生一些 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服务提供商,并且他们可能安装了也可能没有安装无限的加密策略文件。

最佳答案

下面是我用来执行密码套件和协议(protocol)的 Java 类。在 SSLSocketFactoryEx 之前,当我可以访问它们时,我正在修改 SSLSocket 上的属性。 Stack Overflow 上的 Java 人员对此提供了帮助,因此很高兴能够将其发布在这里。

SSLSocketFactoryEx 更喜欢更强大的密码套件(如 ECDHEDHE),它忽略了弱密码套件(如 RC4 MD5)。当 TLS 1.2可用时,它确实必须启用四个 RSA key 传输密码才能与 Google 和 Microsoft 互操作。他们是 TLS_RSA_WITH_AES_256_CBC_SHA256TLS_RSA_WITH_AES_256_CBC_SHA 和两个 friend 。如果可能,您应该删除 TLS_RSA_* key 传输方案。

使密码套件列表尽可能小。如果您宣传所有个可用密码(类似于 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

该列表省略了弱/受伤的算法,例如 RC4 和 MD5。如果它们被启用,那么您可能会得到 Obsolete cryptography warning from Browser偶尔。

使用默认 JCE 策略时,列表会更小,因为该策略删除了 AES-256 和其他一些。我认为它大约有 7 个具有受限策略的密码套件。

SSLSocketFactoryEx 类还确保使用 TLS 1.0 及更高版本的协议(protocol)。 Java 8 之前的 Java 客户端禁用 TLS 1.1 和 1.2。 SSLContext.getInstance("TLS") 也会潜入 SSLv3(即使在 Java 8 中),因此必须采取措施将其移除。

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

关于java - 为 SSL 套接字启用哪些密码套件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1037590/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com