2017-07-06 16 views
1

私のアンドロイドデバイスでは、特定のWebサイトにアクセスできるように手動で証明書をインストールしました。Android - プログラマティックにキーストアから証明書を取得する(手動インストール)

セキュリティ - ユーザー証明書を見ると、私の証明書が見えます。

私のウェブサイトは、WebViewのに表示されたので、私は私のloadCertificateAndPrivateKey()関数では、次のコード

@Override 
public void onReceivedClientCertRequest(WebView view, final ClientCertRequest request) { 
    if (mCertificates == null || mPrivateKey == null) { 
     loadCertificateAndPrivateKey(); 
    } 
    request.proceed(mPrivateKey, mCertificates); 
} 

を使用する必要がありますされて、私はこの

KeyStore ks = KeyStore.getInstance("AndroidCAStore"); 
if (ks != null) 
{ 
    ks.load(null, null); 
    Enumeration<String> aliases = ks.aliases(); 
    while (aliases.hasMoreElements()) 
    { 
     String alias = (String) aliases.nextElement(); 
     java.security.cert.X509Certificate cert = (java.security.cert.X509Certificate) ks.getCertificate(alias); 
     if(cert.getIssuerDN().getName().contains("TOTO")){ 
      mCertificates = new X509Certificate[1]; 
      mCertificates[0] = (X509Certificate)cert; 


      mPrivateKey = ??; 

     } 
    } 

のような証明書を取得するためですが、私秘密鍵を取得する方法を知らない...
私はこの方法を試しましたが、キーオブジェクトはnullです(私のアプリケーションから直接証明書を読み込むと同じコードが動作します)

Key key = keyStore.getKey(alias, password.toCharArray()); 
if (key instanceof PrivateKey) { 
    mPrivateKey = (PrivateKey)key; 
} 

だから私はいくつかの質問を持っている:

  • は、それが証明書を取得するための正しい方法は何ですか?
  • 証明書のパスワードを使用して秘密鍵を取得できないのはなぜですか?
  • このprivateKeyを取得するにはどうすればよいですか?

あなたの答えはTankです。

+0

どのAndroid搭載版をターゲットにしていますか? – nandsito

+0

私はAndroid 6でテストしていますが、Android 4.2.2(ただしAPI 17 = AndroidCAStoreにアクセスできない)で動作すると良いでしょう。しかし、優先順位はAndroid 6 – Ludo

+0

です。証明書を使用してWebサイトにアクセスする場合は、証明書の秘密鍵は必要ありません。また、アンドロイドに秘密鍵をインストールしないでください。秘密鍵が欠落しているようで、それはOKです – nandsito

答えて

1

私はそれを行う方法を見つけました。誰かを助けることを願っています。

私は、processus全体の実装方法を説明するthis linkに続いています。

最後に、コードを取得しました。 まず、KeyChainAliasCallbackを定義し、証明書ストアにアクセスするユーザー権限を持つアクティビティを表示するKainChain.choosePrivateKeyAliasを呼び出します。

KeyChainAliasCallback keyChainAliasCallback = new KeyChainAliasCallback() { 
    @Override 
    public void alias(@Nullable String s) { 
     Log.d(TAG, "selected alias = " + s); 
     asyncTask.execute(); 
    } 
}; 
KeyChain.choosePrivateKeyAlias(this, keyChainAliasCallback, null, null, null, -1, CERT_ALIAS); 

その後、あなたは内部ストアから秘密鍵と証明書チェーンを取得することができます次に

AsyncTask<Void, Void, Boolean> asyncTask = new AsyncTask<Void, Void, Boolean>() { 

    private Exception error; 

    @Override 
    protected Boolean doInBackground(Void... arg) { 
     try { 

      PrivateKey pk = KeyChain.getPrivateKey(mContext, CERT_ALIAS); 
      X509Certificate[] chain = KeyChain.getCertificateChain(mContext, CERT_ALIAS); 

      byte[] data = "foobar".getBytes("ASCII"); 
      Signature sig = Signature.getInstance("SHA1withRSA"); 
      sig.initSign(pk); 
      sig.update(data); 
      byte[] signed = sig.sign(); 

      PublicKey pubk = chain[0].getPublicKey(); 
      sig.initVerify(pubk); 
      sig.update(data); 
      boolean valid = sig.verify(signed); 
      Log.d(TAG, "signature is valid: " + valid); 

      if(valid) { 
       mPrivateKey = pk; 
       mCertificates = chain; 
      } 

      return valid; 
     } catch (Exception e) { 
      e.printStackTrace(); 
      error = e; 

      return null; 
     } 
    } 

    @Override 
    protected void onPostExecute(Boolean valid) { 
     if (error != null) { 
      Toast.makeText(mContext, "Error: " + error.getMessage(), 
        Toast.LENGTH_LONG).show(); 

      return; 
     } else { 
      Toast.makeText(mContext, "Signature is valid: " + valid, 
        Toast.LENGTH_SHORT).show(); 
      mWebView.loadUrl("https://blablabla.com"); 
     } 


    } 
}; 

を(あなたは非同期機能を使用する必要があります)、あなたが証明書を与えることができるしていますこの関数は:

@Override 
public void onReceivedClientCertRequest(WebView view, final ClientCertRequest request) { 
    request.proceed(mPrivateKey, mCertificates); 
} 

私が見つけなければならない最後のことは、choosePrivateKeyAliasダイアログを1回だけ(最初の)表示する方法です。