2012-09-10 18 views
8

मैं Android के लिए एक सरल OpenSSLHttpsUrlConnection वस्तु का उपयोग कर सर्वर से कनेक्ट करने के लिए हो रही परेशानी आ रही है का उपयोग कर (मैं StackOverflow और एक के माध्यम से कंघी कर लिया है ऑनलाइन ट्यूटोरियल का गुच्छा, और उदाहरण के बाद लाइन के लिए बहुत अधिक पंक्ति का पालन किया और मैं अभी भी यह नहीं समझ सकता कि मेरा स्थानीय ट्रस्टस्टोर का उपयोग करते समय मेरा टूटा क्यों है)।एंड्रॉयड HttpsURLConnection javax.net.ssl.SSLException कनेक्शन सहकर्मी हाथ मिलाना त्रुटि द्वारा बंद कर दिया जब स्थानीय truststore

मैं वर्तमान में एक Android गतिविधि है कि करने के लिए कनेक्ट करने का प्रयास करता है एक सरल OpenSSL server (मैं अपने सर्वर एक OpenSSL ग्राहक का उपयोग करने के लिए कनेक्ट कर सकते हैं), एक बार HttpsUrlConnection.connect() कहा जाता है मैं गलत तरीके से एक "javax.net.ssl.SSLException: Connection closed by peer" error during the SSL handshake. शायद मैं की स्थापना कर रहा हूँ मेरी नमूना सर्वर प्राप्त ?

बातें ध्यान रखें:

  • पल
  • बजे जब डिफ़ॉल्ट विश्वास दुकान
  • लोड हो रहा है https://www.google.com से कनेक्ट करने में सक्षम में कोई ग्राहक प्राधिकरण
  • स्व-हस्ताक्षरित प्रमाणपत्र के साथ स्थानीय होस्ट पर सर्वर से कनेक्ट करने में सक्षम नहीं हूँ
  • सभी प्रमाणपत्र पर विश्वास नहीं करने के लिए नहीं करना चाहती
  • अपाचे HttpClient उपयोग करने के लिए
  • स्थानीय truststore केवल
  • स्थानीय बनाई उपयोग करना चाहते हैं नहीं करना चाहती उछाल वाले महल
  • बजे सही ढंग से
  • एक प्रॉक्सी फ़ायरवॉल के पीछे
  • में truststore लोड करने में सक्षम के साथ truststore, प्रॉक्सी मेरी एंड्रॉयड वर्चुअल डिवाइस
  • AVDकरने के लिए सेट पर सेट किया गया है।

बातें मैं पहले से ही की कोशिश की है:

  • 'URL u = new URL("https", "10.0.2.2", 443, "/");'
  • बजाय TrustManagerFactory.getDefaultAlgorithms() का उपयोग कर "X509"
      साथ URL बनाने के लिए एक नया SecureRandom() with the SSLContext.init()
    • का उपयोग कर दोनों 127.0.0.1 and 10.0.2.2
    • से कनेक्ट कर रहा
    • इसके बजाय "Unexpected response code error 503" देता है की
  • "कनेक्शन सहकर्मी द्वारा बंद कर दिया"

समय मेरे सवाल की समीक्षा करने के लेने के लिए अग्रिम धन्यवाद!

$ sudo openssl s_server -accept 443 -cert server-cert.pem -key server-key.pem -pass file:passphrase.txt -state -www -verify 0 

क्लाइंट कनेक्शन आदेश के साथ परीक्षण किया:

सरल सर्वर कमांड के साथ शुरू कर दिया

$ openssl s_client -connect 127.0.0.1:443 

एंड्रॉयड गतिविधि कोड (सरलीकरण के लिए पूर्ण चल कोड निकालने के लिए संपादित - मुझे अगर अधिक कोड बताएं आवश्यक है) - त्रुटि आउटपुट कोड के नीचे है।

try { 
     TrustManagerFactory tmf; 

     // local trust store 
     tmf = TrustManagerFactory.getInstance("X509"); 
     tmf.init(loadLocalKeyStore(getApplicationContext())); 

     // default trust store - works for https://www.google.com 
     // tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
     // tmf.init((KeyStore) null); 

     SSLContext context = SSLContext.getInstance("TLS"); 
     context.init(null, tmf.getTrustManagers(), null); 

     HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.STRICT_HOSTNAME_VERIFIER; 
     URL u = new URL("https://10.0.2.2"); 

     HttpsURLConnection urlConnection = (HttpsURLConnection) u.openConnection(); 

     urlConnection.setSSLSocketFactory(context.getSocketFactory()); 
     urlConnection.setHostnameVerifier(hostnameVerifier); 
     urlConnection.connect(); 

     System.out.println("Response Code: " + urlConnection.getResponseCode()); 
     System.out.println("Response Code: " + urlConnection.getCipherSuite()); 
    } 

    ... 

    private KeyStore loadLocalKeyStore(Context context) { 
     InputStream in = context.getResources().openRawResource(R.raw.newserverkeystore); 
     KeyStore trusted = null; 
     try { 
      trusted = KeyStore.getInstance("BKS"); 
      trusted.load(in, "thisisasecret".toCharArray()); 
     } finally { 
      in.close(); 
     } 
     return trusted; 
    } 

आउटपुट जब https://www.google.com को सही ढंग से जोड़ने:

09-09 21:58:09.947: I/System.out(669): Response Code: 200 
09-09 21:58:09.947: I/System.out(669): Response Code: TLS_ECDHE_RSA_WITH_RC4_128_SHA 

आउटपुट जब स्व-हस्ताक्षरित प्रमाणपत्र के साथ अपने सर्वर से कनेक्ट करने की कोशिश कर रहा:

09-09 22:03:23.377: D/HttpsProxy(717): Https Request error 
09-09 22:03:23.377: D/HttpsProxy(717): javax.net.ssl.SSLException: Connection closed by peer 
09-09 22:03:23.377: D/HttpsProxy(717): at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method) 
09-09 22:03:23.377: D/HttpsProxy(717): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:395) 
09-09 22:03:23.377: D/HttpsProxy(717): at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:210) 
09-09 22:03:23.377: D/HttpsProxy(717): at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:478) 
09-09 22:03:23.377: D/HttpsProxy(717): at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:442) 
09-09 22:03:23.377: D/HttpsProxy(717): at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:289) 
09-09 22:03:23.377: D/HttpsProxy(717): at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:239) 
09-09 22:03:23.377: D/HttpsProxy(717): at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:80) 
09-09 22:03:23.377: D/HttpsProxy(717): at libcore.net.http.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:165) 
09-09 22:03:23.377: D/HttpsProxy(717): at com.example.myfirstapp.HttpsUrlConnectionActivity$3.doInBackground(HttpsUrlConnectionActivity.java:257) 
09-09 22:03:23.377: D/HttpsProxy(717): at com.example.myfirstapp.HttpsUrlConnectionActivity$3.doInBackground(HttpsUrlConnectionActivity.java:1) 
09-09 22:03:23.377: D/HttpsProxy(717): at android.os.AsyncTask$2.call(AsyncTask.java:287) 
09-09 22:03:23.377: D/HttpsProxy(717): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) 
09-09 22:03:23.377: D/HttpsProxy(717): at java.util.concurrent.FutureTask.run(FutureTask.java:137) 
09-09 22:03:23.377: D/HttpsProxy(717): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) 
09-09 22:03:23.377: D/HttpsProxy(717): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076) 
09-09 22:03:23.377: D/HttpsProxy(717): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569) 
09-09 22:03:23.377: D/HttpsProxy(717): at java.lang.Thread.run(Thread.java:856) 

एक बार फिर धन्यवाद !!

+0

मैं यह उल्लेख करना भूल गया कि जब मैं एंड्रॉइड एमुलेटर से कनेक्ट करने का प्रयास करता हूं तो मुझे कोई सर्वर गतिविधि नहीं दिखाई देती है, केवल मेरे ओपनएसएसएल क्लाइंट के साथ। – aspergillusOryzae

+0

इस प्रश्न को प्रारूपित करना बहुत मुश्किल है ;-) –

+0

क्षमा करें, क्या कोई तरीका है जिससे मैं प्रश्न को वोट करने से पहले समझना आसान बना सकता हूं? मैं उन्हें फिर से निर्देशित करने से पहले अन्य पदों से ली गई विधियों की व्याख्या करने की कोशिश कर रहा था। – aspergillusOryzae

उत्तर

6

मैंने अपनी समस्या हल की - मुझे सामान्य नाम (सीएन) के रूप में 10.0.2.2 के साथ प्रमाणपत्र का उपयोग करने की आवश्यकता थी, इसलिए यह 'लोकलहोस्ट' या '127.0.0.1' के बजाय 10.0.2.2 के एंड्रॉइड लोकलहोस्ट आईपी पते से मेल खाता था।

संपादित करें: आप विषय वैकल्पिक नाम (SAN) के रूप में सीएन और '127.0.0.1' और '10 .0.2.2 'के रूप में स्थानीयहोस्ट के साथ प्रमाणपत्र बना सकते हैं।

एक बार मैं 10.0.2.2 प्रमाणपत्र और निजी कुंजी पीईएम फ़ाइलें बनाई, मैं अपने सर्वर निम्न आदेश के साथ चल हिट करने के लिए कर रहा था:

openssl s_server -accept 8888 -cert 10.0.2.2-cert.pem -key 10.0.2.2-key.pem -state -www 

आप (हालांकि एक प्रमाण पत्र प्रदान करने के लिए ग्राहक के लिए मजबूर करना चाहते हैं इसे चेक नहीं किया जाएगा), ऊपर दिए गए आदेश पर ध्वज -Verify 1 जोड़ें।

कमांड लाइन आप निम्नलिखित का उपयोग कर सकते पर सर्वर का परीक्षण करने के (ध्यान दें openssl 127.0.0.1 के माध्यम से कनेक्ट करने में सक्षम है):

openssl s_client -connect 127.0.0.1:8888 

और एक ग्राहक प्रमाणपत्र जोड़ने के लिए है, तो सर्वर इसे की आवश्यकता है, को जोड़ने झंडे -cert client-cert.pem -key client-key.pem

मेरे Android ग्राहक में मैं कनेक्ट करने के लिए निम्नलिखित कोड का इस्तेमाल किया (त्रुटि हटाया जाँच):

// use local trust store (CA) 
TrustManagerFactory tmf; 
KeyStore trustedStore = null; 
InputStream in = context.getResources().openRawResource(R.raw.mycatruststore); // BKS in res/raw 
trustedStore = KeyStore.getInstance("BKS"); 
trustedStore.load(in, "insertBksPasswordHere".toCharArray()); 
tmf = TrustManagerFactory.getInstance("X509"); 
tmf.init(trustedStore); 

// load client certificate 
KeyStore clientKeyStore = loadClientKeyStore(getApplicationContext()); 
KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509"); 
kmf.init(clientKeyStore, "insertPasswordHere".toCharArray()); 

SSLContext context = SSLContext.getInstance("TLS"); 

// provide client cert - if server requires client cert this will pass 
context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 
HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.STRICT_HOSTNAME_VERIFIER; 

// connect to url 
URL u = new URL("https://10.0.2.2:8888/"); 
HttpsURLConnection urlConnection = (HttpsURLConnection) u.openConnection(); 
urlConnection.setSSLSocketFactory(context.getSocketFactory()); 
urlConnection.setHostnameVerifier(hostnameVerifier); 
urlConnection.connect(); 
System.out.println("Response Code: " + urlConnection.getResponseCode()); 

आप 2 की प्रतिक्रिया कोड मिलना चाहिए 00, और वहां से प्रतिक्रिया विच्छेदन कर सकते हैं। 7 घंटे यह समस्या सुलझा नहीं है और अंत में -

private KeyStore loadClientKeyStore(Context context) { 
    InputStream in = context.getResources().openRawResource(R.yourKeyStoreFile); 
    KeyStore trusted = null; 
    trusted = KeyStore.getInstance("BKS"); 
    trusted.load(in, "yourClientPassword".toCharArray()); 
    in.close(); 
    return trusted; 
} 
2

मैं व्यर्थ मेरी 6:

यहाँ ग्राहक साख लोड करने के लिए कोड है, जो सर्वर कुंजी संग्रह लोड हो रहा है, लेकिन एक अलग संसाधन फ़ाइल नाम और पासवर्ड के साथ समान है है यह

public void URLConnection(String webUrl) throws IOException, NoSuchAlgorithmException, KeyManagementException { 
     //TLSSocketFactory objTlsSocketFactory = new TLSSocketFactory(); 
     URL url = new URL(webUrl); 
     HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection(); 
     urlConnection.setRequestMethod("GET"); 
     //urlConnection.setSSLSocketFactory(objTlsSocketFactory); 

     int responseCode = urlConnection.getResponseCode(); 
     System.out.println("\nSending 'GET' request to URL : " + url); 
     System.out.println("Response Code : " + responseCode); 

     BufferedReader in = new BufferedReader(
       new InputStreamReader(urlConnection.getInputStream())); 
     String inputLine; 
     StringBuffer response = new StringBuffer(); 

     while ((inputLine = in.readLine()) != null) { 
      response.append(inputLine); 
     } 
     in.close(); 

     //print result 
     System.out.println(response.toString()); 
    } 

और यह काम किया !!!!!!

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