2012-03-07 15 views
7

का उपयोग करके मुझे एक कस्टम/स्टैंडअलोन जावा वेबसर्वर लागू करने का कार्य सौंपा गया है जो उसी पोर्ट पर SSL और गैर-SSL संदेशों को संसाधित कर सकता है।एसएसएल हैंडशेकिंग स्व-हस्ताक्षर किए गए कर्ट और एसएसएलईजीएन (जेएसएसई)

मैंने एक एनआईओ सर्वर लागू किया है और यह गैर-एसएसएल अनुरोधों के लिए काफी अच्छा काम कर रहा है। मुझे एसएसएल टुकड़े के साथ एक समय का एक बिल्ली है और वास्तव में कुछ मार्गदर्शन का उपयोग कर सकता है।

यहां मैंने जो किया है, वह यहां है।

एसएसएल और गैर-एसएसएल संदेशों के बीच अंतर करने के लिए, मैं इनबाउंड अनुरोध के पहले बाइट को यह देखने के लिए जांचता हूं कि यह एक एसएसएल/टीएलएस संदेश है या नहीं। उदाहरण:

byte a = read(buf); 
    if (totalBytesRead==1 && (a>19 && a<25)){ 
     parseTLS(buf); 
    } 

parseTLS में() विधि मैं इस तरह एक SSLEngine का दृष्टांत:

java.security.KeyStore ks = java.security.KeyStore.getInstance("JKS"); 
    java.security.KeyStore ts = java.security.KeyStore.getInstance("JKS"); 

    ks.load(new java.io.FileInputStream(keyStoreFile), passphrase); 
    ts.load(new java.io.FileInputStream(trustStoreFile), passphrase); 

    KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 
    kmf.init(ks, passphrase); 

    TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); 
    tmf.init(ts); 

    SSLContext sslc = SSLContext.getInstance("TLS");  
    sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 


    SSLEngine serverEngine = sslc.createSSLEngine(); 
    serverEngine.setUseClientMode(false); 
    serverEngine.setEnableSessionCreation(true); 
    serverEngine.setWantClientAuth(true); 

एक बार SSLEngine instantiated है, मैं सीधे बाहर कोड का उपयोग कर खोलना/रैप तरीकों का उपयोग कर भीतर का डेटा की प्रक्रिया आधिकारिक JSSE Samples की:

log("----"); 

    serverResult = serverEngine.unwrap(inNetData, inAppData); 
    log("server unwrap: ", serverResult); 
    runDelegatedTasks(serverResult, serverEngine); 

    log("----"); 

    serverResult = serverEngine.wrap(outAppData, outNetData); 
    log("server wrap: ", serverResult); 
    runDelegatedTasks(serverResult, serverEngine); 

हाथ मिलाना के पहले भाग ठीक से काम करने लगता है। ग्राहक एक हाथ मिलाना संदेश भेजता है और सर्वर 4 रिकॉर्ड के साथ एक संदेश के साथ प्रतिक्रिया करता है:

handshake (22) 
- server_hello (2) 
- certificate (11) 
- server_key_exchange (12) 
- certificate_request (13) 
- server_hello_done (14) 

इसके बाद, ग्राहक को तीन भागों के साथ एक संदेश भेजता है:

handshake (22) 
- certificate (11) 
- client_key_exchange (16) 

change_cipher_spec (20) 
- client_hello (1) 

handshake (22) 
*** Encrypted Message **** 

SSLEngine ग्राहक के अनुरोध और पार्स करता है unwraps रिकॉर्ड लेकिन रैप विधि ठीक/NEED_UNWRAP की हैंडशेक स्थिति के साथ 0 बाइट उत्पन्न करती है। दूसरे शब्दों में, मेरे पास क्लाइंट को वापस भेजने के लिए कुछ भी नहीं है और हैंडशेक एक डरावना ठहराव के लिए आता है।

यह वह जगह है जहां मैं अटक गया हूं।

डीबगर में, मैं देख सकता हूं कि एसएसएलईएनजीएन, विशेष रूप से सर्वरहैंडशेकर, को कोई सहकर्मी कर्ट नहीं मिला है। यह स्पष्ट है जब मैं क्लाइंट से प्रमाण पत्र रिकॉर्ड देखता हूं जो कि 0 बाइट लंबा है। पर क्यों?

मैं केवल यह मान सकता हूं कि हैलोसेवर प्रतिक्रिया में कुछ गड़बड़ है लेकिन मैं अपनी अंगुली को उस पर नहीं डाल सकता। सर्वर एक मान्य प्रमाण भेज रहा है लेकिन ग्राहक कुछ भी वापस नहीं भेज रहा है। क्या मेरे कीस्टोर में कोई समस्या है? या यह ट्रस्टस्टोर है? या क्या एसएसएलईजीएनआईएन को तुरंत चालू करने के तरीके से कुछ करना है? मैं उलझन में हूं।

युगल अन्य बिंदुओं:

  • कुंजीस्टोर और truststore कोड SNIPPIT ऊपर निम्नलिखित ट्यूटोरियल का उपयोग बनाया गया था में संदर्भित: http://www.techbrainwave.com/?p=953
  • मैं परीक्षण करने के लिए ग्राहक के रूप में फ़ायरफ़ॉक्स 10 और IE 9 उपयोग कर रहा हूँ सर्वर। दोनों वेब क्लाइंट के लिए वही परिणाम।
  • मैं सूर्य/ओरेकल जेडीके 6 और जावा सिक्योर सॉकेट एक्सटेंशन (जेएसएसई) का उपयोग कर रहा हूं जो इसके साथ आता है।

मैं किसी भी मार्गदर्शन आप हो सकता है लेकिन मुझे मत बताओ कृपया मैं पागल हो रहा हूँ या Netty या ग्रिजली या कुछ अन्य मौजूदा समाधान का उपयोग करने के लिए तत्पर हैं। यह इस समय सिर्फ एक विकल्प नहीं है। मैं सिर्फ यह समझना चाहता हूं कि मैं क्या गलत कर रहा हूं।

अग्रिम में धन्यवाद!

+0

बस एक बेवकूफ सवाल: क्या आपने क्लाइंट प्रमाण पत्र जेनरेट और स्थापित किए हैं फ़ायरफ़ॉक्स HTTPS के माध्यम से अपने वेब-सर्वर से कनेक्ट करते समय? – Robert

+0

हां। एफएफ ने मुझे प्रमाण पत्र स्वीकार/अस्वीकार करने के लिए प्रेरित किया। मैंने "तकनीकी जोखिम स्वीकार करते हैं" पर क्लिक किया और मैं उपकरण-> विकल्प-> उन्नत-> एन्क्रिप्शन-> प्रमाणपत्र देखें-> सर्वर के अंतर्गत प्रमाण देख सकता हूं। वास्तव में, एफएफ इसके बिना दूसरा हैंडशेक संदेश नहीं भेजेगा। – Peter

+0

यही वह नहीं है जो मैं पूछ रहा था। मैं ग्राहक प्रमाण पत्र के लिए पूछ रहा था। एसएसएल क्लाइंट प्रमाणीकरण वैकल्पिक है और ज्यादातर कॉर्पोरेट वातावरण में उपयोग किया जाता है, अक्सर चिप-कार्ड के संयोजन में। यदि ग्राहक के पास प्रमाण पत्र स्थापित नहीं है (फ़ायरफ़ॉक्स अनुभाग "आपका प्रमाणपत्र") तो यह एक नहीं भेजेगा। – Robert

उत्तर

9

आपको NEED_UNWRAP मिल गया है, इसलिए एक अनचाहे करें। यह बदले में आपको BUFFER_UNDERFLOW दे सकता है, जिसका अर्थ है कि आपको पढ़ना और अनचाहे पुनः प्रयास करना होगा।

इसी प्रकार जब आप NEED_WRAP प्राप्त करते हैं, तो एक लपेटें: जो बदले में आपको BUFFER_OVERFLOW दे सकता है, जिसका अर्थ है कि आपको लिखना है और रैप को पुनः प्रयास करना है।

उस लपेटने या अनचाहे बदले में आपको एक और ऑपरेशन करने के लिए कह सकता है: लपेटें या खोलें।

बस ऐसा करें जो आपको करने के लिए कहता है।

+0

हां, मैंने NEED_UNWRAP देखने के बाद अनचाहे करने की कोशिश की लेकिन पढ़ने के लिए और कुछ भी नहीं है। मैं दूसरे क्लाइंट हैंडशेक को तार में पूरी तरह से देख सकता हूं और एसएसएलईजीएनई सभी इसे पार कर सकता है। दुर्भाग्य से, यह क्लाइंट को वापस भेजने के लिए मेरे लिए कोई आउटपुट नहीं बनाता है। ग्राहक थोड़ा इंतजार कर रहा है और अंत में लटका हुआ है। – Peter

+1

@ पीटर वहां पढ़ने के लिए कुछ भी नहीं हो सकता है लेकिन अभी भी कुछ अनचाहे हो सकता है। जैसा मैंने कहा, वैसा ही करें, यह बताएं कि हर अनचाहे को पढ़ने के बजाय पढ़ने के बजाय कब पढ़ना है। आम तौर पर हैंडशेक में सर्वर की पहली प्रतिक्रिया में उदाहरण के लिए तीन अलग-अलग संदेश होते हैं, इसलिए आपको एक पंक्ति में 3 NEED_WRAPs मिलेंगे: इसके विपरीत क्लाइंट शायद एक ही पठन में सब कुछ पढ़ेगा लेकिन तीन लगातार NEED_UNWRAPS प्राप्त करेगा। पूरे हैंडशेक में भी लागू होता है। – EJP

+0

ठीक है, शांत। ईजेपी और थोड़ा और डिबगिंग के लिए धन्यवाद, मैं समझता हूं कि अब क्या हो रहा है। एसएसएलईजीएन एक समय में एक रिकॉर्ड खोल रहा है। तो दूसरे क्लाइंट हैंडशेक में, वास्तव में 3 रिकॉर्ड हैं: हैंडशेक, change_cipher_spec, और एक और हैंडशेक। मैं केवल एक बार अनचाहे बुला रहा था इसलिए एसएसएलईएनजीएन ने केवल पहला रिकॉर्ड पार्स किया था। क्लाइंट को वापस भेजने के लिए किसी बाइट उत्पन्न करने से पहले सभी रिकॉर्ड्स को संसाधित करने की आवश्यकता थी। मैं अंततः आवेदन डेटा वापस प्राप्त कर रहा हूँ! – Peter

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