JavaのSSLSocketを使用して、クライアントとサーバープログラム間の通信を保護しています。サーバープログラムは、WebブラウザーからのHTTPS要求も処理します。
371ページの「 Javaでの暗号化の開始 」に従って、setEnabledCipherSuites
/SSLSocket
で常にSSLServerSocket
を呼び出して、最終的にネゴシエートされる暗号スイートが目的に対して十分強力であることを確認する必要があります。
そうは言っても、私の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 サービスプロバイダーにアクセスでき、無制限の暗号化ポリシーファイルがインストールされている場合とされていない場合があります。
エクスポートでは何も使用しないでください。強力な暗号化に関する輸出規制のため、これはクリップルウェアです。
編集:2009ドキュメントを使用するように変更されました。
2009 NIST recommendation は、TLS_RSA_WITH_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
以下は、Javaクラスを使用して、暗号スイートとプロトコルを適用します。SSLSocketFactoryEx
の前は、SSLSocket
にアクセスしていたときに、それらのプロパティを変更していました。 。Java Stack Overflowの人々が助けてくれたので、ここに投稿できるのは素晴らしいことです。
SSLSocketFactoryEx
は、より強力な暗号スイート(ECDHE
やDHE
など)を優先し、(_RC4
_および_MD5
_など)弱くて傷のある暗号スイートを省略します。 TLS 1.2が利用できない場合、GoogleおよびMicrosoftとの相互運用のために4つのRSAキートランスポート暗号を有効にする必要があります。彼らは_TLS_RSA_WITH_AES_256_CBC_SHA256
_、_TLS_RSA_WITH_AES_256_CBC_SHA
_と2人の友達です。可能であれば、_TLS_RSA_*
_キー転送スキームを削除する必要があります。
暗号スイートのリストはできるだけ小さくしてください。 all利用可能な暗号を宣伝する場合(Flaschenのリストと同様)、リストは80+になります。これはClientHello
で160バイトを消費し、ClientHello
を処理するための小さな固定サイズのバッファーがあるため、一部のアプライアンスが失敗する可能性があります。壊れたアプライアンスにはF5とIronportが含まれます。
実際には、優先リストがJavaでサポートされている暗号スイートと交差すると、以下のコードのリストは10または15の暗号スイートにペアになります。たとえば、無制限のJCEポリシーを設定してMicrosoft.comまたはgoogle.comに接続する準備をするときに取得するリストは次のとおりです。
このリストでは、RC4やMD5などの弱い/負傷したアルゴリズムは省略されています。それらが有効になっている場合、おそらく ブラウザーからの暗号化の警告が廃止 が時々表示されます。
デフォルトの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
_暗号スイートは、現在の一部のスイートよりもはるかに高速であり、より優れたセキュリティプロパティを備えているため、可能であれば推奨されます。グーグルはすでにそれをサーバーに展開している。 Oracleがそれらをいつ提供するかはわかりません。 OpenSSLはOpenSSLを提供します 1.0.21.1. 。
次のように使用できます。
_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;
}
_