2015-11-14 10 views
5

मैं एक वित्तीय लेनदेन एंड्रॉइड ऐप बना रहा हूं। इसे एसएसएल प्रमाणीकरण की आवश्यकता है और मैं इसे सफलतापूर्वक पूरा करने में सक्षम हूं (एंड्रॉइड और टॉमकैट के बीच हैंडशेक)। मैंने सर्वर और क्लाइंट प्रमाणपत्र उत्पन्न करने के लिए keytool और openSSL का उपयोग किया। टॉमकैट प्रमाण पत्र प्रारूप जेकेएस है और एंड्रॉइड फॉर्मेट बीकेएस है। मैं कच्चे फ़ोल्डर में इस बीकेएस फ़ाइल संग्रहीत और इस प्रकार इस का उपयोग करें:एंड्रॉइड - प्रोग्रामस्ट्रीम में कीस्टोर में सर्टिफिकेट कैसे स्टोर करें?

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 कनेक्शन का उपयोग कर उपयोगकर्ता पंजीकृत करना चाहते हैं। प्रक्रिया उपयोगकर्ता से विवरण प्राप्त करती है और इसे सर्वर पर भेजती है। सर्वर इन विवरणों को सत्यापित करेगा और उपयोगकर्ता मोबाइल पर पुष्टिकरण पिन भेज देगा (उपयोगकर्ता विवरण में यह एमएसआईएसडीएन मिला है)। उपयोगकर्ता इस पिन को दर्ज करेगा और सर्वर सत्यापित करेगा कि पिन समान है। उपयोगकर्ता सत्यापित होने के बाद क्लाइंट ऐप (उपयोगकर्ता मोबाइल) एक सीएसआर उत्पन्न करेगा और इसे सर्वर पर भेज देगा। सर्वर इस सीएसआरएंड का उपयोग कर सर्टिफिकेट जेनरेट करेगा क्लाइंट (मोबाइल ऐप) को भेज देगा। अब मेरी समस्या यह है कि मैं इस प्रमाणपत्र को स्टोर करना चाहता हूं जहां केवल मेरा ऐप इस प्रमाणपत्र तक पहुंच सके। मैं इस का उपयोग करते हुए कच्चे फ़ोल्डर में मेरी बीकेएस फ़ाइल में इस को बचाने के लिए कोशिश कर रहा हूँ:

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

इस कोड को सफलतापूर्वक चलता लेकिन बीकेएस फ़ाइल में प्रमाणपत्र की दुकान नहीं कर सका। मैंने here का वर्णन करने का एक और तरीका कोशिश की लेकिन सफल नहीं हो सका। (मैं क्लाइंट प्रमाणीकरण के लिए बाद में अपने ऐप में इस प्रमाणपत्र का उपयोग करना चाहता हूं) मेरा प्रश्न है प्रश्न: मैं इस प्रमाणपत्र को कैसे स्टोर कर सकता हूं ताकि यह केवल मेरे ऐप द्वारा पहुंचा जा सके? और उपयोगकर्ता पंजीकरण समाप्त होने पर भी मैं इस प्रमाणपत्र को हटा सकता हूं।

कृपया अग्रिम में सहायता करें और धन्यवाद।

उत्तर

2
  • आपका मुद्दा कीस्ट्रोक के साथ ही नहीं है, बल्कि फ़ाइल के स्थान है जहाँ आप नए ग्राहक प्रमाणपत्र संगृहीत करने का प्रयास कर रहे हैं!
  • "रॉ-फ़ोल्डर" आपके इंस्टॉल किए गए एप्लिकेशन पैकेज का हिस्सा है। तो आप इसे "वर्चुअल" तक पहुंच सकते हैं, और केवल पढ़ सकते हैं, लिखना नहीं!
  • यदि आप अपनी कीस्टोर निजी होना चाहते हैं तो आपका सबसे अच्छा विकल्प, एप्लिकेशन सैंडबॉक्स-निजी-फ़ोल्डर (आंतरिक संग्रहण) है।
    आप रॉ फ़ोल्डर में नहीं लिख सकते हैं, लेकिन आप अपने एप्लिकेशन निजी फ़ोल्डर में लिख सकते हैं।
  • link में आपके द्वारा प्रदान किया, भंडारण/लिखने स्थान तथ्य निजी फ़ोल्डर में है। तो यह है क्योंकि आप को "रॉ-फ़ोल्डर में लिखने" कोशिश कर रहे हैं आप के लिए काम नहीं किया
  • आप शायद पहले से ही पता है, लेकिन आप से अपनी फ़ाइल (R.raw.client) कॉपी कर सकते हैं आपके एप्लिकेशन निजी फ़ोल्डर में "रॉ-फ़ोल्डर"। इस तरह, आप केवल एक कीस्टोर फ़ाइल (पठनीय और लिखने योग्य) का उपयोग करते हैं।
+0

क्या आप कृपया बता सकते हैं कि मैं एक नया कीस्टोर कैसे बना सकता हूं और फिर बाद में उपयोग के लिए उस कुंजीस्टोर में अपना प्रमाणपत्र संग्रहीत कर सकता हूं। मैं एसएसएल हैंडशेक के लिए इस प्रमाणपत्र का उपयोग करूंगा। –

संबंधित मुद्दे