17

サーバーが 1024 ビットより長いキーを送信したときに発生するエラー「DH キーペアを生成できませんでした」に関する以前の投稿を読みました。JCE 無制限の jar をダウンロードすると、この問題が修正されます。テスト環境では、同じ Web サーバーで Java 6 を使用すると https クエリを実行してもエラーは発生しませんが、Java 7 を使用すると「DH キーペアを生成できませんでした」というメッセージが表示されます。

JCE 無制限の jar ファイルを置き換えようとしましたが、それでも同じエラーが発生します。このバグは 2007 年から報告されていますが、Java 7 ではなく Java 6 で実行されるのはなぜですか? ダウンロードするファイルは適切なものではありませんか? 以前の投稿Java: Why does SSL handshake give 'Could not generate DH keypair' exception?からリンクを取得しました。.

この時点で、私は何をすべきかわかりません。BouncyCastle プロバイダーをロードしようとすると、ArrayOutOfIndex 例外が発生します。私のサーバーでは DH アルゴリズムしか許可されていないため、上記の投稿で提案されているような別のアルゴリズムを使用することはできません。

4

5 に答える 5

11

いくつかの追加または説明:

(Suncle) 7u09 以降の Java 7 では、7u04 の一見ランダムな順序とは異なり、デフォルトでより賢明で一貫した順序の暗号スイートが使用されます。(04 から 09 の間のテストはありません。) この順序では、ECDHE とプレーン RSA (別名 akRSA) が DHE の前に配置されるため、サーバーが ECDHE または RSA をサポートし、クライアントの設定に同意する場合にのみ、問題が回避されます。(または ECDH で修正されていますが、実際には誰もそれを使用していません。) サーバーが (何らかの理由で) DHE を主張し、かつ DH>1024 ビットを使用している場合、まだ問題があります。

質問者 (または他の誰か) が本当に整数 DH (ECDH や RSA ではない) を必要とするサーバーに接続する場合、8 より前の Java で動作する唯一の方法は、サーバーに DH 1024 ビットを使用させることです。どの AFAWK が技術的にはあと数年は安全ですが、NIST などの重要な機関によって禁止されています (csrc.nist.gov の Special Pub 800-57 を参照)。(RSA 1024 でさえ、実際にはまだ壊れていませんが、おそらくすぐに壊れるので、禁止されています。)

「無制限の強さのポリシー」は、この問題に関連していないか、少なくとも直接的ではありません。SunJCE の DH パラメータの制限は変更されません。これは (誤って) 強度の問題ではなく標準の問題として扱われます。(具体的には、DSA に対して適切であった制限を DH に適用します。) AES-256 および SHA-2 (TLSv1.2 のみ) スイートを有効にし、十分に奇妙な優先リストを指定すると、選択結果を DHE (失敗) から非 DHE (動作) に変更します。

Java 6 リストに完全に戻る必要はありません。DHE よりも他の鍵交換を優先するか、または反抗的なサーバーの場合は DHE を完全に削除する必要があります。レガシー サーバーでどうしても必要な場合を除き、EXPORT またはシングル DES スイートの有効化に戻るべきではありません。それらは数年前から安全ではなく、本来よりもはるかに長い間、デフォルトで有効なままでした。

于 2014-02-07T00:59:40.383 に答える
8

私は SSLScokets で同じ問題に出くわしましたが、Java 7 でこの回帰の理由を特定したと思います。その理由は、クライアントとサーバーの間でネゴシエートされた暗号にあります。

デフォルトでは、Java 6 は TLS 接続に対してこれらの暗号を有効にします (優先順位に従って)。

SSL_RSA_WITH_RC4_128_MD5
SSL_RSA_WITH_RC4_128_SHA
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_DHE_RSA_WITH_AES_128_CBC_SHA
TLS_DHE_DSS_WITH_AES_128_CBC_SHA
SSL_RSA_WITH_3DES_EDE_CBC_SHA
SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
SSL_RSA_WITH_DES_CBC_SHA
SSL_DHE_RSA_WITH_DES_CBC_SHA
SSL_DHE_DSS_WITH_DES_CBC_SHA
SSL_RSA_EXPORT_WITH_RC4_40_MD5
SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
TLS_EMPTY_RENEGOTIATION_INFO_SCSV

また、Java 7 ではこれらの暗号が有効になります。

TLS_DHE_RSA_WITH_AES_128_CBC_SHA
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
SSL_RSA_WITH_RC4_128_SHA
TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
TLS_ECDHE_RSA_WITH_RC4_128_SHA
TLS_ECDH_ECDSA_WITH_RC4_128_SHA
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
TLS_ECDH_RSA_WITH_RC4_128_SHA
TLS_EMPTY_RENEGOTIATION_INFO_SCSV
TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
SSL_RSA_WITH_RC4_128_MD5
TLS_DHE_DSS_WITH_AES_128_CBC_SHA
SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
SSL_RSA_WITH_3DES_EDE_CBC_SHA

Java 7 では Diffie-Hellman を使用する暗号が優先されますが、強力な暗号パッケージがインストールされていない限り、1024 ビットを超えるキーはサポートされないようです。

私が使用した回避策は、Java 6 で有効になっている暗号を次のように指定することでしたSSLSocket

SSLSocketFactory socketFactory = SSLContext.getInstance("TLS").getSocketFactory();
SSLSocket socket = (SSLSocket) socketFactory.createSocket(InetAddress.getByName(hostname), port);
socket.setEnabledCipherSuites(new String[] {
        "SSL_RSA_WITH_RC4_128_MD5",
        "SSL_RSA_WITH_RC4_128_SHA",
        "TLS_RSA_WITH_AES_128_CBC_SHA",
        "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
        "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
        "SSL_RSA_WITH_3DES_EDE_CBC_SHA",
        "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
        "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
        "SSL_RSA_WITH_DES_CBC_SHA",
        "SSL_DHE_RSA_WITH_DES_CBC_SHA",
        "SSL_DHE_DSS_WITH_DES_CBC_SHA",
        "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
        "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
        "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
        "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
        "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"});

socket.startHandshake();
于 2012-07-27T12:57:30.567 に答える
7

最新の Java エディションを使用していてもエラーが発生する場合は、java.security の設定を変更できます (たとえば、フォルダー C:\Program Files\Java\jre1.8.0_xx\lib\security 内)。

# Example:
#   jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
    jdk.tls.disabledAlgorithms=SSLv3, RC4

jdk.tls.disabledAlgorithms で DH を無効なアルゴリズムとして追加

    jdk.tls.disabledAlgorithms=SSLv3, RC4, DH

tomcat を再起動するか、プログラムを再実行してください。

于 2015-11-03T10:57:40.433 に答える
2

Java7 と Java8 でもこの問題に直面していました。また、Emanual Borg の提案に似た回避策も使用しました。しかし、私たちの目標は、CipherSuites の固定リストをハードコーディングしないようにすることでした。そのため、問題の原因となったエントリを削除してみました (試行錯誤により...)。

String[] enabledCipherSuites = socket.getEnabledCipherSuites();

// avoid hardcoding a new list, we just remove the entries
// which cause the exception
List<String> asList = new ArrayList(Arrays.asList(enabledCipherSuites));

// we identified the following entries causeing the problems
// "Could not generate DH keypair"
// and "Caused by: java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive)"
asList.remove("TLS_DHE_RSA_WITH_AES_128_CBC_SHA");
asList.remove("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA");
asList.remove("TLS_DHE_RSA_WITH_AES_256_CBC_SHA");

String[] array = asList.toArray(new String[0]);
socket.setEnabledCipherSuites(array);

質問: このアプローチに問題がある人はいますか?

ところで: Apache HTTPClient を使用している場合、https: //issues.apache.org/jira/browse/HTTPCLIENT-1111は興味深いもので、メソッドを介して CipherSuites (HTTPClient v4.2 以降) を設定する方法を示しています。

SSLConnectionSocketFactory() {...}.prepareSocket(SSLSocket)

2015/10/31 更新: これを使用するコンテキストをよりよく理解するために、フックインして prepareSocket() メソッドをオーバーライドする方法を示す完全な疑似コードの例を以下に示します。

HttpClientBuilder builder = HttpClients.custom();

SSLContextBuilder sslContextBuilder = SSLContexts.custom();
SSLContext sslContext = sslContextBuilder.build();

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, hostNameVerfier)
{


    protected void prepareSocket(SSLSocket socket) throws IOException {

    // Workaround to use different order of CipherSuites used by Java6 in order
        // to avoid the the problem of java7 "Could not generate DH keypair"
        String[] enabledCipherSuites = socket.getEnabledCipherSuites();

        // but to avoid hardcoding a new list, we just remove the entries
        // which cause the exception (via TrialAndError)
        List<String> asList = new ArrayList(Arrays.asList(enabledCipherSuites));

        // we identified the following entries causeing the problems
        // "Could not generate DH keypair"
        // and "Caused by: java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive)"
        asList.remove("TLS_DHE_RSA_WITH_AES_128_CBC_SHA");
        asList.remove("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA");
        asList.remove("TLS_DHE_RSA_WITH_AES_256_CBC_SHA");

        String[] array = asList.toArray(new String[0]);
        socket.setEnabledCipherSuites(array);

    };
};

Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create().register("https", sslsf).build();

PoolingHttpClientConnectionManager conman = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
builder.setConnectionManager(conman);

CloseableHttpClient httpClient =  builder.build();

注意 してください このコードは、ユーザーが明示的に自己署名証明書の信頼を有効にするコンテキスト (テスト環境など) でのみ使用しています。これをしたくない場合は、SSL をいじらないほうがよいでしょう。

于 2015-09-02T14:10:13.057 に答える
1

jdk1.7.0_04 を使用している場合は、jdk1.7.0_21 にアップグレードします。そのアップデートで問題が修正されました。

于 2013-05-22T08:35:06.727 に答える