2011-12-09 17 views
54

これらは、分かりやすくするために別々の質問として表現することもできますが、すべて同じ問題に関連しています。SSL証明書サーバー名の解決方法/ keytoolを使用して代替名を追加できますか?

SSL証明書サーバー名はどのように解決されていますか?

ブラウザは証明書のCNフィールドを使用しているように見えますが、Javaのメカニズムは「主体代替名」だけを見るように見えるのはなぜですか?

keytoolを使用してSSL証明書に代替名を追加することはできますか? そうでない場合は、代わりにopenSSLを使用していますか?

ちょっとした背景: HTTPSを使用して複数のサーバーと通信するためにメインサーバーを取得する必要があります。当然のことながら、私たちはすべてのサーバー(多くの場合があります)にSSL証明書を購入したくないので、自己署名証明書を使用したい(私はkeytoolを使って証明書を生成しています)。証明書をOSに信頼できるものとして追加すると、ブラウザ(IEとChrome)はその接続を信頼できるものとしてうれしく受け入れます。しかし、Javaのcacertsファイルに証明書を追加した後、Javaはまだ信頼されたような接続を受け入れ、以下の例外スローしません:java.security.cert.CertificateException:によって引き起こさ

ないサブジェクト代替名 存在を (sunname.Checker.java:75) X509TrustManagerImpl.checkIdentity(X509T rustManagerImpl.java:264) (com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted( X509TrustManagerImpl.java:250)私は、Javaが私を実装する証明書を信頼することができますことを発見しcom.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(CLIEN tHandshaker.java:1185)より ... 14

でここからコピーした自分のHostNameVerifier:com.sun.jbi.internal.security.https.DefaultHostnameVerifier(ちなみに、HostnameVerifierの引数として渡されたホスト名は正しいので、受け入れられているはずです)。

私は証明書フィールドCNをホスト名(通常はIPアドレス)として使用しています。

誰かが私に何か間違っていることを教えてもらい、正しい方向に向けることができますか?

+1

リンクが壊れています。 – axiopisty

+1

あなたの代わりを選んでください:http://grepcode.com/search?query=DefaultHostnameVerifier&n= – Renato

答えて

82

ホスト名の確認方法は、RFC 6125で定義されています。これは最近のもので、すべてのプロトコルに対して一般的なもので、HTTPS固有のRFC 2818を置き換えます。 RFC 2818 (Section 3.1)から

(。私は、Java 7には、このためにあまりにも最近のかもしれないRFC 6125を使用していますさえわからない):

型のdNSNameのsubjectAltName拡張が存在する場合、そのMUSTを使用すること アイデンティティとして。それ以外の場合は、証明書のSubjectフィールドの(最も固有の)Common Name フィールドを使用する必要があります。 共通名の使用は既存の方法で行われますが、推奨されておらず、代わりに 認証機関にdNSNameを使用することをお勧めします。いくつかのケースでは

[...]

、URIは、IPアドレスではなく ホスト名として指定されています。この場合、iPAddressのsubjectAltNameは証明書の中に でなければならず、URIのIPと正確に一致する必要があります。

本質的に、特定の問題は、ホスト名ではなくCNでIPアドレスを使用していることに起因します。特に、RFC 2818の「最も具体的」が明確に定義されていないため、すべてのツールが厳密にこの仕様に準拠しているわけではないため、一部のブラウザが動作する場合があります(RFC 6215の説明を参照)。

あなたがkeytoolを使用している場合、as of Java 7, keytoolは(-extのドキュメントの表を参照)サブジェクトの別名を含めるオプションがあります:あなたは-ext san=dns:www.example.com-ext san=ip:10.0.0.1を使用することができます。

EDIT:

あなたはグローバル設定を編集したくない場合は(それは、私が覚えている限りでは、現在のディレクトリにコピーを選択しますopenssl.cnfを変更することにより、OpenSSLのでSANを要求することができます環境変数OPENSSL_CONFを使用して明示的な場所を選択することもできます)。このため、環境変数を使用するにはすてきなトリック(というで設定ファイルでそれを固定より)ここにもあります

[req] 
req_extensions = v3_req 

[ v3_req ] 
subjectAltName=IP:10.0.0.1 
# or subjectAltName=DNS:www.example.com 

は、次のオプションが(最初の括弧内の適切なセクションを見つける。)に設定します。 http://www.crsr.net/Notes/SSL.html

+0

これは私が知る必要があったものですが、Java 6にはこの-extオプションがないようです。 VMをJava 7に変更してテストします。 – Renato

+2

Java 7のkeytoolを別のマシンで使用し、後でキーストアをコピーすることができます(Java 7を実行する必要はありません)。代わりに、私はOpenSSLでそれを行うための私の答えを編集しました。これは、長期的にはIPアドレスの代わりにホスト名を使用するほうが柔軟性が高いことがわかります(SANを使用すると良い考えです)。 – Bruno

+0

-extオプションはJava6では機能しません!私はJava 7に切り替えて、keytoolを使ってやってみることができるかどうかを見てみましょう...答えが大変ありがとうございます。(PSは一度テストしたら答えを受け入れるでしょう) – Renato

関連する問題