2017-08-11 8 views
1

スマートカードを使用してウェブサイトにログインする必要があります。ユーザーの証明書と非エクスポート可能な秘密鍵(通常のPrivateKeyオブジェクトですが、「getEncoded」メソッドはnullを返します)を含むスマートカードからキーストアを正常に取得できます。Javaでのクライアント証明書認証

このサイト:https://pst.giustizia.it/PST/authentication/it/pst_ar.wp には、訪問するたびに変更されるログインリンクがあります。ユーザーが行うように、私はJavaアプリケーションで同じことを行います。そのページを一度訪れてそのリンクを取得した後、そのリンク上でSSL認証を実行します(ページを訪問してそのリンクをクリックするようなものです) 。

これは私が使用するコードです:

public class SSLAuth 
{ 
    private static String LOGIN_PAGE = "https://pst.giustizia.it/PST/authentication/it/pst_ar.wp"; 
    private static String USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0"; 

    private TrustStrategy trustStrategy = new TrustStrategy() 
    { 
     public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException 
     { 
      // Temporary work-around. I already know how to fix this 
      return true; 
     } 
    }; 

    public String authenticate(String pin) throws Exception 
    { 
     // Request KeyStore from smart card 
     KeyStore keyStore = Utility.digitalSigner.loadKeyStorePKCS11(); 
     SSLContext sslContext = SSLContexts.custom().useProtocol("TLSv1.2").loadTrustMaterial(keyStore, trustStrategy).build(); 

     // Get login token first 
     String loginToken = null; 
     { 
      Document document = Jsoup.connect(LOGIN_PAGE).ignoreContentType(true).userAgent(USER_AGENT).timeout(10000).followRedirects(true).get(); 
      Elements link = document.select("div > fieldset > p > a"); 
      loginToken = link.get(0).attr("abs:href"); 
     } 

     // Try to authenticate 
     HttpClient httpClient = HttpClients.custom().setUserAgent(USER_AGENT).setSSLContext(sslContext).build(); 
     HttpResponse response = httpClient.execute(new HttpGet(loginToken)); 
     if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) 
      return null; 

     return response.toString(); 
    } 
} 

一度、ウェブサイトをチェックのみ「JSESSIONID」という名前のCookieとクライアントのユーザーエージェント文字列をログインしたので、私は、最初の時間を認証するだけで済みます。私はすでにこれをテストしました。これら2つの有効なパラメータがあれば、別のブラウザからでもこのページにアクセスできます。

"loadKeyStorePKCS11"メソッドは、認証チェーン(99%、多分100%は1つの証明書だけです)を含む上記のキーストアを提供します。26種類のスマートカードを試したので、ユーザのもの)と、エクスポート不可能な秘密鍵とを含む。 私は解決策についてインターネットを見ようとしましたが、PKCS#12についてはすべてですが、これは必要ありません。

私は別のプロトコル(SSLとTLS)とそれの異なるバージョンを使用しようとしましたが、何もしませんでした!

Firefoxはスマートカード認証を行うことができますが、手順で何か不足していることがわかりました。 "httpClient"オブジェクトの "execute"メソッドを呼び出すと、 "handshake_failure"(SSLHandshakeException)例外が発生します。

「loadTrustMaterial」の代わりに「loadKeyMaterial」を使用すると、「unsupported_certificate」が取得されます。

私はこの時点で何をすべきか分かりません。 アドバイスをお持ちですか? ありがとうございます!

+1

エラーの理由を確認するには、 '-Djavax.net.debug = ssl:handshake'をJVMに追加します。私の推測は、信頼できないルートCAまたは暗号不一致です。 –

+0

[こちら](https://www.dropbox.com/s/94m10zrfhpy4zmb/ConsoleMessage.txt?dl=0)コンソールログ全体を見つけることができます。最初の80行は、スマートカードドライバからのデバッグメッセージです。残りはハンドシェイクデバッグからのものです。前もって感謝します! – FonzTech

+0

残念ながら、Dropboxはプロキシサーバーによってブロックされています。 –

答えて

1

ログを送信していただきありがとうございます。私は、コメントにはあまりにも多いので、これを回答にします。

短答:サーバーがクライアント証明書を要求していて、ユーザーが証明書を持っていないか、または受け入れ可能な証明書を提供するように構成されていません。このため、あなたのログで

検索:

main, READ: TLSv1 Handshake, length = 11296 
*** CertificateRequest 
Cert Types: RSA, DSS 
Cert Authorities: 

これは、クライアント証明書をお願いサーバーです。以下は、受け入れ可能なCAのリストです。これらのCAのいずれかによって発行されたキーストアに証明書が必要であり、クライアント側のセッションでクライアント証明書を有効にする必要があります。

*** ServerHelloDone 
Warning: no suitable certificate found - continuing without client 
authentication 

を残念ながら、あなたがサーバーに受け入れ証明書を持っていない、またはクライアント証明書モードに設定されていないようだと、それはあなたをカットする理由です:

ログの次の部分は、これは言いますオフにしてハンドシェイクを打ち切ります。

+0

こんにちは!お返事をありがとうございます。 [こちら](http://i.imgur.com/NXyhh68.jpg)あなたは私の証明書を見つけることができます。これは、許容されるCAにリストされているCAによって発行されています。だから私は問題が何か他のものだと思う...アドバイスはありますか? – FonzTech

+0

"loadTrustMaterial"を "loadKeyMaterial"に変更しました。 "*** CertificateVerify"の直後に "unsupported_certificate"が表示されます。これは何を意味するのでしょうか?前もって感謝します! – FonzTech

+0

証明書をキーストアからファイルにエクスポートし、次にopensslを使ってそれをチェックします: 'openssl x509 -in -inform der -text -noout'。署名アルゴリズムと公開鍵アルゴリズムを確認してください。ログファイルには、サポートされている証明書の種類が「RSA」と「DSS」であることが記載されています。 –

関連する問題