2015-11-14 19 views
5

私は金融取引のアンドロイドアプリを作っています。 SSL認証が必要で、それを正常に完了できます(AndroidとTomcat間のハンドシェイク)。私はkeytoolとopenSSLを使ってサーバーとクライアント証明書を生成しました。 Tomcatのcertifcate形式はJKSで、android formateはBKSです。私は生のフォルダにこのBKSファイルを保存し、次のようにこれを使用する:Android - キーストアに証明書をプログラムで保存する方法

public class NetworkCallSecure extends AsyncTask<String, Void, String> { 

ResponseListener responseListener; 
Activity activity; 
ResultCodes code; 

public NetworkCallSecure(Activity activity, ResponseListener responseListener, ResultCodes code) { 
    this.responseListener = responseListener; 
    this.activity = activity; 
    this.code = code; 
} 

@Override 
protected String doInBackground(String... params) { 

    try{ 

     System.setProperty("http.keepAlive", "false"); 
     HttpsURLConnection .setDefaultHostnameVerifier(new HostnameVerifier() { 

        public boolean verify(String hostname, 
              SSLSession session) { 
         Log.d("HTTPS",hostname+":"+session); 
         return true; 
        } 
       }); 

     char[] passwKey = "mypass".toCharArray(); 
     KeyStore ks = KeyStore.getInstance("BKS"); 
     InputStream in = activity.getResources().openRawResource(
       R.raw.client); 
     InputStream is = activity.getResources().openRawResource(
       R.raw.client); 
     ks.load(in, passwKey); 
     KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509"); 
     kmf.init(ks, passwKey); 

     SSLContext context = SSLContext.getInstance("TLS"); 
     context.init(kmf.getKeyManagers(), 
       new X509TrustManager[] { new MyX509TrustManager(is, 
         passwKey) }, new SecureRandom()); 
     HttpsURLConnection.setDefaultSSLSocketFactory(context 
       .getSocketFactory()); 

     URL url = new URL(params[0]); 

     HttpsURLConnection connection = (HttpsURLConnection) url 
       .openConnection(); 
     connection.setRequestMethod("POST"); 
     connection.setRequestProperty("Content-Type", "application/json"); 
     connection.setRequestProperty("Content-Length", "" + Integer.toString(params[1].getBytes().length)); 
     connection.setDoOutput(true); 

     byte[] outputInBytes = params[1].getBytes("UTF-8"); 
     OutputStream os = connection.getOutputStream(); 
     os.write(outputInBytes); 
     os.close(); 

     BufferedReader bin = new BufferedReader(new InputStreamReader(
       connection.getInputStream())); 

     StringBuffer sb = new StringBuffer(); 
     String line; 
     while ((line = bin.readLine()) != null) { 
      sb.append(line); 
     } 
     in.close(); 
     is.close(); 
     return sb.toString(); 
    } catch (Exception e) { // should never happen 
     e.printStackTrace(); 
     Log.d("Err", e.toString()); 
    } 
    return "no result"; 
} 

@Override 
protected void onPostExecute(String result) { 
    responseListener.getResponse(result,code); 
} 
} 

私のTrustManagerクラスです:

public class MyX509TrustManager implements X509TrustManager { 
X509TrustManager pkixTrustManager; 

public MyX509TrustManager(InputStream trustStore, char[] password) 
     throws Exception { 
    // create a "default" JSSE X509TrustManager. 

    KeyStore ks = KeyStore.getInstance("BKS"); 

    ks.load(trustStore, password); 

    TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509"); 
    tmf.init(ks); 

    TrustManager tms[] = tmf.getTrustManagers(); 

    /* 
    * Iterate over the returned trustmanagers, look for an instance of 
    * X509TrustManager. If found, use that as our "default" trust manager. 
    */ 
    for (int i = 0; i < tms.length; i++) { 
     if (tms[i] instanceof X509TrustManager) { 
      pkixTrustManager = (X509TrustManager) tms[i]; 
      return; 
     } 
    } 

    /* 
    * Find some other way to initialize, or else we have to fail the 
    * constructor. 
    */ 
    throw new Exception("Couldn't initialize"); 
} 

public void checkClientTrusted(X509Certificate[] arg0, String arg1) 
     throws CertificateException { 
    // TODO Auto-generated method stub 
    try { 
     pkixTrustManager.checkClientTrusted(arg0, arg1); 
    } catch (CertificateException excep) { 
     // do any special handling here, or rethrow exception. 
    } 

} 

public void checkServerTrusted(X509Certificate[] arg0, String arg1) 
     throws CertificateException { 
    // TODO Auto-generated method stub 
    try { 
     pkixTrustManager.checkServerTrusted(arg0, arg1); 
    } catch (CertificateException excep) { 
     /* 
     * Possibly pop up a dialog box asking whether to trust the cert 
     * chain. 
     */ 
    } 
} 

public X509Certificate[] getAcceptedIssuers() { 
    // TODO Auto-generated method stub 
    return pkixTrustManager.getAcceptedIssuers(); 
} 
} 

は今、私はこのHTTPS接続を使用して、ユーザーを登録します。プロセスは、ユーザーからの詳細を取得し、サーバーに送信します。サーバーはこれらの詳細を確認し、ユーザーの携帯に確認PINを送信します(ユーザーの詳細でこのMSISDNを取得します)。ユーザーはこのPINを入力し、サーバーはPINが同じであることを確認します。ユーザーが確認された後、クライアントアプリケーション(ユーザーモバイル)はCSRを生成し、サーバーに送信します。サーバーはこのCSRを使用して証明書を生成し、それをクライアント(モバイルアプリ)に送信します。 私の問題は、私のアプリケーションだけがこの証明書にアクセスできる場所にこの証明書を保存したいということです。私はこれを使用して、生のフォルダ内の私のBKSファイルでこれを保存しようとしています:

private boolean storeCertInKeystore(byte[] cert) { 
    try { 
     InputStream is = getResources().openRawResource(
       R.raw.client); 
     CertificateFactory cf = CertificateFactory.getInstance("X.509"); 
     InputStream certstream = new ByteArrayInputStream(cert); 
     X509Certificate certificate = (X509Certificate) cf.generateCertificate(certstream); 
     KeyStore keyStore = KeyStore.getInstance("BKS"); 
     keyStore.load(is, "mypass".toCharArray()); 
     keyStore.setCertificateEntry("mycert", certificate); 


     Log.d("My App Cert: ", "true"); 
     return true; 
    } catch(Exception e) { 
      e.printStackTrace(); 
    } 
    return false; 
} 

このコードは正常に実行されますがBKSファイルに証明書格納されませんでした。私は別の方法でhereを記述しようとしましたが、成功できませんでした。 (私はクライアント認証のために私のアプリでこの証明書を後で使用したい) 私の質問はQです。私のアプリでのみアクセスできるようにこの証明書を保存するにはどうしたらいいですか?また、ユーザー登録の有効期限が切れたときにこの証明書を削除することもできます。

ご協力いただきありがとうございます。

答えて

2
  • あなたの問題は、ストア自体ではなく、むしろ新しいクライアント 証明書を保存しようとしているファイルの 場所ではありません!
  • "RAW-folder"は、インストールされたアプリケーションパッケージの一部です。だから あなたは "事実上"それにアクセスすることができます。
  • キーストアをプライベートにする場合は、 アプリケーションsandboxed-private-folder(内部ストレージ)を使用することをお勧めします。
    RAWフォルダに書き込むことはできませんが、アプリケーションのプライベートフォルダに書き込むことはできます。あなたが提供link
  • 、ストレージ/書き込み位置は 実際にプライベートフォルダです。あなたは をしようとしているので、だから、
  • 書き込みRAW-フォルダに」あなたはおそらく既に知っている、しかし、あなたはあなたのファイル(R.raw.client)をコピーすることができますあなたのために動作しませんでしたから "Raw-folder"をアプリケーションのプライベートフォルダに追加します。この方法では、1つのキーストアファイル(読み書き可能)のみを使用します。
+0

新しいキーストアを作成し、後で使用するためにそのキーストアに証明書を保存する方法を教えてください。この証明書をSSLハンドシェイクに使用します。 –

関連する問題