私が最近遭遇した以下の問題を使用して、Javaのセキュリティプロバイダー、暗号、および暗号化全般をよりよく理解したいと思っています。
Solaris 10ホストから、SSLハンドシェイク中に InstallCert ツールを使用して、Java 1.6.0_81を実行して2つのADホストの1つに)を実行すると、次のエラーが発生しました。
]$ Java InstallCert Host1.example.com:636
Loading KeyStore /usr/jdk/instances/jdk1.6.0/jre/lib/security/cacerts...
Opening connection to Host1.example.com:636...
Starting SSL handshake...
javax.net.ssl.SSLException: Java.lang.RuntimeException: Could not parse key values
at com.Sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.Java:190)
at com.Sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.Java:1747)
at com.Sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.Java:1708)
at com.Sun.net.ssl.internal.ssl.SSLSocketImpl.handleException(SSLSocketImpl.Java:1691)
at com.Sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.Java:1222)
at com.Sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.Java:1199)
at InstallCert.main(InstallCert.Java:98)
Caused by: Java.lang.RuntimeException: Could not parse key values
at Sun.security.pkcs11.P11Key$P11ECPublicKey.fetchValues(P11Key.Java:954)
at Sun.security.pkcs11.P11Key$P11ECPublicKey.getW(P11Key.Java:975)
at com.Sun.net.ssl.internal.ssl.ECDHClientKeyExchange.<init>(ECDHClientKeyExchange.Java:40)
at com.Sun.net.ssl.internal.ssl.ClientHandshaker.serverHelloDone(ClientHandshaker.Java:782)
at com.Sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.Java:241)
at com.Sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.Java:593)
at com.Sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.Java:529)
at com.Sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.Java:943)
at com.Sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.Java:1188)
at com.Sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.Java:1215)
... 2 more
Caused by: Java.io.IOException: extra data given to DerValue constructor
at Sun.security.util.DerValue.init(DerValue.Java:368)
at Sun.security.util.DerValue.<init>(DerValue.Java:277)
at Sun.security.pkcs11.P11Key$P11ECPublicKey.fetchValues(P11Key.Java:945)
... 11 more
2番目のホストはエラーを出しません。ここで収集できた唯一の違いは、Host1.example.com
の暗号です。これはAES256-SHAです。 Host2.example.com
の暗号はAES128-SHAです。
]$ echo -n | openssl s_client -connect Host1.example.com:636 | grep 'Cipher is'
New, TLSv1/SSLv3, Cipher is AES256-SHA
]$ echo -n | openssl s_client -connect Host2.example.com:636 | grep 'Cipher is'
New, TLSv1/SSLv3, Cipher is AES128-SHA
私の質問は:
Host1.example.com
でのAES256-SHAの暗号化についてどうですか?問題を解決するために、最終的にこのセキュリティプロバイダーをJava.security
ファイルでコメント化しました。
security.provider.1=Sun.security.pkcs11.SunPKCS11 ${Java.home}/lib/security/sunpkcs11-solaris.cfg
バグの多いプロバイダー とCipherのこの組み合わせがこの問題の原因であると思われますか?そのリンクは「EC」を参照していますが、それが何かはわかりません。
ポインタと洞察は大歓迎です!
さらに具体的には、ECDHはDiffie-Hellmanの楕円曲線バリアントであり、ここでは鍵交換に使用されます。ほとんど確実にECDHE、ephemeralECDHの形式ですが、ここの情報から確認することはできません。
サーバー上で「the」暗号を言うことはできません。実質的にすべてのSSL/TLS実装は、複数の暗号スイート(省略された、不正確な暗号)をサポートしています。通常、クライアントはクライアントがサポートするスイートの大きなリストを提供し、サーバーはサーバーがサポートするスイートの中から「最良の」スイートを選択します。この場合、「最良の」ものは複雑であり、(多くの)他の質問があります。 。 AD ass-u-me ADがWindows Active Directoryを意味する場合でも、サポートするスイートがわからないため、Windowsのバージョン、およびおそらくADのバージョンに依存すると考えています。
Host1に対するJava6の試みは、サーバーが選択したECDHを使用して少なくとも1つのスイートを提供したが、Sun PKCS11プロバイダーでは機能しませんでした。 Solarisについては確信がありませんが、SunのWindowsおよびLinux Java6ディストリビューションには組み込みのECCプロバイダーが含まれていなかったため、PKCS11が(申し立てにより)サポートしているものへのアクセスを提供しない限り、ECDHスイートを提供(または同意)しません。 Java7と8doにはECCが組み込まれていますが、プロバイダーポジション1にPKCS11がある場合でも優先されます。
あなたのopenssl s_client
がHost1でプレーンなRSAスイートをネゴシエートしました。 (OpenSSL名AES256-SHAは、実際にはTLS_RSA_WITH_AES_256_CBC_SHAを意味します。歴史的な理由により、OpenSSL名はプレーンRSA鍵交換のRSAを省略します。)OpenSSLバージョン0.9。*はデフォルトでECCをサポートせず、この結果を生成します。 (技術的には、十分に上手く行けば0.9.8でECCを実行できますが、そうだと思います。)OpenSSL(アップストリーム)1.0.0以降は、すべての標準ECDHスイートをサポートします。そして、それらを好みます、サーバーに1つを選択させると私は期待します。 OpenSSLのRedHatパッケージは、最近の特許の問題までECCが省略されていることは知っています。明らかにRedHatはSolarisには適用されませんが、おそらく(a?)Solarisパッケージャーが同じことをしたのかもしれません。誰かがビルドを微調整してECCをサポートしたがそれを好まなかった可能性もあり、サーバーはその設定に従いました。 -cipher ECDH:!aNULL
を追加して、ECDHスイートの取得に成功するかどうかを確認し、成功するかどうかを確認します。
Javaで乱暴に信頼する:いずれの場合も、opensslではInstallCert
は必要ありません。行う
echo Q | openssl s_client -connect $Host:$port -showcerts \
| nawk '/--BEG/,/--END/{print>"anchor"} /--END/{close("anchor")}'
つまり、-showcerts
を追加して、証明書データのlastブロックをファイルに選択し、次に
keytool -keystore $YOURJRE/lib/security/cacerts -importcert -file anchor -alias $NAME
ここで、$NAME
は、文字と数字の短い名前only地方自治体(ドメインなど)のニーモニックであり、パスワードを入力しますchangeit
と確認します。
Javaセキュリティプロバイダーの目的と暗号化におけるそれらの役割は何ですか?
私のjdk/jre/lib/security/Java.securityファイルからの抜粋:
#
# This is the "master security properties file".
#
# In this file, various security properties are set for use by
# Java.security classes. This is where users can statically register
# Cryptography Package Providers ("providers" for short). The term
# "provider" refers to a package or set of packages that supply a
# concrete implementation of a subset of the cryptography aspects of
# the Java Security API. A provider may, for example, implement one or
# more digital signature algorithms or message digest algorithms.
#
# Each provider must implement a subclass of the Provider class.
# To register a provider in this master security properties file,
# specify the Provider subclass name and priority in the format
#
# security.provider.<n>=<className>
#
# This declares a provider, and specifies its preference
# order n. The preference order is the order in which providers are
# searched for requested algorithms (when no specific provider is
# requested). The order is 1-based; 1 is the most preferred, followed
# by 2, and so on.
#
# <className> must specify the subclass of the Provider class whose
# constructor sets the values of various properties that are required
# for the Java Security API to look up the algorithms or other
# facilities implemented by the provider.
#
# There must be at least one provider specification in Java.security.
# There is a default provider that comes standard with the JDK. It
# is called the "Sun" provider, and its Provider subclass
# named Sun appears in the Sun.security.provider package. Thus, the
# "Sun" provider is registered via the following:
#
# security.provider.1=Sun.security.provider.Sun
#
# (The number 1 is used for the default provider.)
#
# Note: Providers can be dynamically registered instead by calls to
# either the addProvider or insertProviderAt method in the Security
# class.
[編集済み]バグの原因に関するdave_thompsonの回答を出して、ここで回答する資格のある1つの質問のみに回答を修正します。