2015-11-14 16 views
5

Ich mache eine finanzielle Transaktion Android App. Es erfordert SSL-Authentifizierung und ich kann es erfolgreich abschließen (Handshake zwischen Android und Tomcat). Ich habe keytool und openSSL verwendet, um Server- und Client-Zertifikate zu generieren. Tomcat Certificate Format ist JKS und Android Formiat ist BKS. Ich dieses BKS-Datei im Raw-Ordner gespeichert und diese wie folgt verwenden:Android - Wie Zertifikat in Keystore programmgesteuert speichern?

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); 
} 
} 

Meine Trust Klasse ist:

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(); 
} 
} 

Jetzt habe ich Benutzer mit dieser HTTPS-Verbindung registrieren möchten. Der Prozess erhält Details vom Benutzer und sendet sie an den Server. Der Server wird diese Details überprüfen und die Bestätigungs-PIN auf dem Benutzer-Handy senden (hat diese MSISDN in den Benutzerdetails erhalten). Der Benutzer gibt diese PIN ein und der Server überprüft, ob die PIN identisch ist. Nachdem der Benutzer überprüft wurde, generiert die Client-App (Benutzer Mobile) eine CSR und sendet sie an den Server. Der Server generiert das Zertifikat mithilfe dieser CSR und sendet es an den Client (mobile App). Jetzt ist mein Problem, ich möchte dieses Zertifikat speichern, wo nur meine App auf dieses Zertifikat zugreifen kann. Ich versuche, dies in meiner BKS-Datei im Raw-Ordnern mit diesem zu speichern:

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; 
} 

Dieser Code erfolgreich ausgeführt wird, aber nicht in der BKS-Datei cert speichern kann. Ich habe versucht, einen anderen Weg beschreiben here aber konnte nicht erfolgreich sein. (Ich möchte dieses Zertifikat später in meiner App für die Client-Authentifizierung verwenden) Meine Frage ist Q. Wie kann ich dieses Zertifikat speichern, damit es nur für meine App zugänglich ist? Außerdem kann ich dieses Zertifikat löschen, wenn die Benutzerregistrierung abläuft.

Bitte helfen und danke im Voraus.

Antwort

2
  • Ihr Problem ist nicht mit dem Schlüsselspeicher selbst, sondern mit dem Speicherort der Datei in dem Sie das neue Client Zertifikat gespeichert sind versuchen!
  • Der "RAW-Ordner" ist Teil Ihres installierten Anwendungspakets. So können Sie "virtuell" darauf zugreifen, und nur lesen, nicht schreiben!
  • Ihre beste Option, wenn Sie möchten, dass Ihr Keystore privat ist, ist Ihre Anwendung Sandboxed-Private-Ordner (Interner Speicher).
    Sie können nicht in den RAW-Ordner schreiben, aber Sie können in den privaten Ordner Ihrer Anwendung schreiben.
  • Im link, dass Sie den privaten Ordner in Tatsache vorgesehen ist, ist die Speicherung/Schreibstelle. So dass es nicht für Sie arbeiten, weil Sie zu „Schreib im Raw-Ordner“ versuchen
  • Sie wahrscheinlich, dass bereits wissen, aber Sie können Ihre Datei (R.raw.client) aus dem Verzeichnis "Raw-Ordner" in den privaten Ordner Ihrer Anwendung. Auf diese Weise verwenden Sie nur eine Keystore-Datei (lesbar und schreibbar).
+0

Könnten Sie bitte sagen, wie kann ich einen neuen Schlüsselspeicher erstellen und dann mein Zertifikat in diesem Schlüsselspeicher für die spätere Verwendung speichern. Ich werde dieses Zertifikat für den SSL-Handshake verwenden. –

Verwandte Themen