この質問は、SunMSCAPI を使用すると TLS クライアント認証が失敗するにも投稿されましたが、回答が見つかりませんでした。
クライアント証明書を必要とするサーバーに接続する Windows Win2008R2 クライアントで Java6 アプリケーションを実行しています。Java アプリケーションは、ネイティブ Windows ストア、つまり Windows-Root および Windows-My を使用する必要があり、SunMSCAPI プロバイダを採用しています。Windows 証明書管理コンソールは、署名したクライアント証明書と CA 証明書の両方が正しく、すべての目的で有効になっていることを報告します。
サーバー検証は期待どおりに機能しますが、秘密鍵が RSA 秘密鍵ではないことを訴える SSLException をクライアントがスローすると、クライアント認証は失敗します。ただし、代わりに Java デフォルト プロバイダが使用され、同じクライアント証明書が JKS キーストアから取得される場合、つまり SunMSCAPI と Windows ストアが使用されない場合、クライアント認証は期待どおりに機能し、SSL 接続は成功します。
実行すると、アプリケーションは SunMSCAPI プロバイダーを使用していることを報告し、正しいクライアント証明書とその RSAPrivateKey に関する情報を出力できます。トレースは、サーバーの証明書要求への応答が準備されているため、サーバーの「Hello Done」の後にクライアント例外が発生したことを示しています。
これのクライアント キーストア部分に関連するコード ビットは次のとおりです。
SSLContext sslContext = SSLContext.getInstance("TLS");
KeyManagerFactory kFac = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
Provider pvdr = new sun.security.mscapi.SunMSCAPI();
Security.insertProviderAt(pvdr,1);
KeyStore kStore = KeyStore.getInstance("Windows-MY",pvdr);
kStore.load(null,null);
kFac.init(kstore,null);
sslContext.init(kFac.getKeyManagers(), <a trust factory>.getTrustManagers(), new java.security.SecureRandom());
SSLSocketFactory sockFactory = SSLSocketFactory(sslContext);
SSLSocket sslSock = (SSLSocket)sockFactory.createSocket(<some destination host>, <some destination port>);
BufferedInputStream bInStr = new BufferedInputStream(sslSock.getInputStream());
bInStr.read(<the read arguments>); <<< exception thrown in here
ポインタや提案は大歓迎です!