web-dev-qa-db-ja.com

認証にクライアント証明書が必要なURLをリクエストする方法

認証にクライアント証明書を使用するサーバーからURLを要求する必要がありますが、アプリケーションでこれを行う方法が見つかりません。

私の問題は、私が作業しているJavaクライアントは、証明書ファイルをローカルで使用できますが、実行するPCの制限により、証明書をキーストアにインストールできないことです。

つまり、取得する必要のあるURLに使用する証明書を明示的に指定できるようにしたいだけです。

助言がありますか?

16
Steve Neal

あなたが話している制限が何であるかは明らかではありません。具体的には、ローカル証明書ファイルとキーストアの違いをどのように考えているのかわかりません。ほとんどのキーストアはファイルベースであるため、インストールプロセスを必要とせずに、この方法でファイルを直接ロードできる場合があります。 JVM自体によって使用されるセキュリティポリシーに関連する制限はありますか(これにより、KeyStoresのインスタンス化が妨げられる可能性があります)?

まず、クライアント側で必要なのは証明書だけではなく、その秘密鍵です。多くの場合、このコンテキストでは「証明書」という単語を両方を意味するために使用しますが、ファイルに秘密鍵のない証明書が含まれていないことを確認する必要があります。通常、秘密鍵と証明書の組み合わせはPKCS#12ファイル(.p12/.pfx)にあり、多くのツールがこの形式でインポート/エクスポートされます。これは、Sun JVMでネイティブにサポートされているキーストア形式でもあります(タイプPKCS12)。

これを機能させるには、適切なキーストアとの接続を確立するものを構成する必要があります。 SSL/TLSクライアント証明書認証は、常にサーバーによって開始されます。クライアントは、証明書を持っている(そしてそれを使用したい)場合、証明書で応答します。特定のURL用に構成するには、接続を確立するもの(おそらくHttpsURLConnection)を見つけて、そこに設定する必要があります(デフォルトのコンテキストで設定されていない限り、デフォルトのコンテキストで設定されている場合でも、それを要求するサーバーに使用されます)。

JVM上でキーストアをグローバルに設定するには(制限により実行できない場合があります)、javax.net.ssl.keyStorejavax.net.ssl.keyStorePassword(および関連する)システムプロパティを設定できます。 (パスワードが表示される可能性があるため、コマンドラインでパスワードを表示しないことをお勧めします)。

これらのシステムプロパティは、デフォルトのSSLContextの構成に使用されます(これは、多くの場合、HttpsURLConnectionなどのライブラリまたはクラスによって透過的に使用されてSSLSocketFactoryを構築し、次にSSLSocketを構築し、これらのプロパティで初期化されます)。

その接続専用にファイルからSSLContextを作成できます。 SSLContextは事実上SSLSocketFactoryまたはSSLEngineのファクトリであり、特定のSSLSocketFactoryHttpsURLConnectionを設定できます。

次の例では、「/ path/to/file.p12」をキーストア(つまり、秘密鍵と送信する証明書を含むもの)として使用してSSLContextを作成し、トラストストアのデフォルト設定を維持します( d入力ストリームの例外もキャッチする必要があります)。

KeyStore ks = KeyStore.getInstance("PKCS12");
FileInputStream fis = new FileInputStream("/path/to/file.p12");
ks.load(fis, "password".toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, "password".toCharArray());
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(kmf.getKeyManagers(), null, null);

そこから、次のように接続を構成できます(これが使用している場合)。

HttpURLConnection connection = (HttpURLConnection) url.openConnection();
if (connection instanceof HttpsURLConnection) {
    ((HttpsURLConnection)connection)
         .setSSLSocketFactory(sc.getSocketFactory());
}

一部のライブラリでは、SSLContextを直接渡すことができます(Apache HTTPクライアント4はそれをサポートしており、これはApache HTTPクライアント3で実行できます これを使用 。)

キーストアをロードするときに直接パラメーターとしてパスワードを指定する必要はないことに注意してください。コールバックを使用することもできます(GUIの観点からはおそらくより良いでしょう)。

おそらく このライブラリ が役立つ可能性があります(ただし、必須ではありません):ヘルパーがこれを行うために KeystoreLoader を使用できます。このライブラリには SSLContextFactories もあります(ただし、信頼管理またはキー選択をカスタマイズするためのラッパーである傾向があるため、ラッパーはおそらく必要ありません)。

これは通常、クライアント証明書の使用を構成する方法ですが、制限が正確に何であるか(および使用しているライブラリ)を明確にせずに詳細を提供することは困難です。

24
Bruno

アプリを呼び出すときに、プロパティを介してデフォルトのJSSEキーストアを変更できます。-Djavax.net.ssl.keystore=somefile

したがって、keytoolコマンドを使用して証明書をキーストアにインポートし、それを指すアプリを呼び出すことができます。

keytool -importcert -file mycert -keystore mystore
Java -Djavax.net.ssl.keystore=mystore ...
1
locka