2012-06-09 23 views
8

के माध्यम से ठीक इसी तरीके से मैं अपने एसएसएल प्रमाणपत्र, कुंजी, आदि उत्पन्न है:SSL प्रमाणपत्र, बचत के माध्यम से प्रमाणीकृत करने नहीं, लेकिन ब्राउज़र

openssl genrsa -out server.key 1024 
openssl rsa -in server.key -out new_key.pem 
openssl req -new -key server.key -out server.csr 
openssl x509 -req -days 10000 -in server.csr -signkey new_key.pem -out server.crt 

यह काम करता है, मैं क्रोम में उत्पादन देख सकते हैं, हालांकि मैं एक मिल चेतावनी है कि मैं पहले वायरस प्राप्त करने जा रहा हूँ।

openssl s_server -cert server.crt -www -key new_key.pem 

यह सर्वर से एक स्निपेट है। मैं ईमानदार हो जाएगा, मुझे यकीन है कि वास्तव में क्या हर पंक्ति कर रही है नहीं कर रहा हूँ हालांकि मैं एक अच्छा विचार है:

socketFactory->server(true); // this is the server 
socketFactory->authenticate(false); // no auth? 
socketFactory->loadCertificate("server.crt"); 
socketFactory->loadPrivateKey("new_key.pem"); 

ग्राहक:

socketFactory->loadTrustedCertificates("server.crt"); 
socketFactory->authenticate(true); //auth? wierd, right? This guy does this:[1] 

[1] http://permalink.gmane.org/gmane.comp.lib.thrift.user/1651

हैं मैं ग्राहक में loadTrustedCertificates बाहर टिप्पणी है, तो मैं एक SSL असत्यापित प्रमाण पत्र अपवाद मिलता है। कि लाइन के साथ में छोड़ दिया, मैं एक प्रमाणन विफलता अपवाद मिलता है।

यहाँ 2 बहुत लंबे समय तक कोड के टुकड़े, कि बेहतर परिप्रेक्ष्य में ऊपर के टुकड़े डाल दिया है।
सर्वर:

shared_ptr<SkullduggeryHandler> handler(new SkullduggeryHandler()); 
shared_ptr<TBufferedTransportFactory> transportFactory = 
     shared_ptr<TBufferedTransportFactory>(new TBufferedTransportFactory()); 
shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory()); 
shared_ptr<TProcessor> processor(new SkullduggeryProcessor(handler)); 
shared_ptr<TSSLSocketFactory> socketFactory = 
     shared_ptr<TSSLSocketFactory>(new TSSLSocketFactory()); 
socketFactory->server(true); 
socketFactory->authenticate(false); 
socketFactory->loadCertificate("server.crt"); 
socketFactory->loadPrivateKey("new_key.pem"); 
shared_ptr<TSSLServerSocket> socket(new TSSLServerSocket(port, socketFactory)); 
TThreadedServer server(processor, 
           socket, 
           transportFactory, 
           protocolFactory); 
server.serve(); 

ग्राहक:

shared_ptr <TSSLSocketFactory> socketFactory = shared_ptr<TSSLSocketFactory>(new TSSLSocketFactory()); 
socketFactory->loadTrustedCertificates("server.crt"); 
socketFactory->authenticate(false); 
shared_ptr <TSSLSocket>socket = socketFactory->createSocket(configuration.ip, configuration.port); 
shared_ptr<TBufferedTransport> transport(new TBufferedTransport(socket)); 
shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport)); 
SkullduggeryClient client(protocol); 
transport->open(); 

समय देने के लिए इस पढ़ने के लिए के लिए धन्यवाद। यदि चमकदार त्रुटियां हैं, तो मुझे इसके बारे में सुनकर खुशी होगी। यह बहुत लंबे समय से मेरे अस्तित्व का झुकाव रहा है। बहुत लंबा।

उत्तर

10

ऐसा लगता है कि आप स्व-हस्ताक्षरित प्रमाणपत्र (जो ठीक है) उत्पन्न कर रहे हैं, लेकिन openssl उपयोगिता के साथ आप जो ऑपरेशन कर रहे हैं, वे भ्रमित हैं।

पंक्ति 1 ठीक है, यह एक निजी कुंजी उत्पन्न करता है।
पंक्ति 2 बेकार है: उत्पादन कुंजी इनपुट कुंजी के रूप में ही है! (diff को देखने के लिए दो कुंजियों का प्रयास करें)।
लाइन 3 एक सीएसआर और लाइन 4 वास्तव में आत्म संकेत यह उत्पन्न करता है, तो वे एक पंक्ति में एक साथ विलय किया जा सकता है के रूप में हम देखेंगे।

अब, चलो एक कदम पीछे ले जाने और के समझने के लिए हम :-)

क्या कर रहे हैं आप SSL का उपयोग कर रहे हैं प्रमाणित करने और एक बचत सर्वर और एक बचत ग्राहक के बीच संचार एन्क्रिप्ट करने के लिए कोशिश करते हैं। मुझे लगता है कि आप दोनों चाहते हैं:

  1. एक दुष्ट सर्वर (क्या आपके कोड करने के लिए प्रयास कर रहा है)
  2. एक दुष्ट ग्राहक से सर्वर (जो मेरे लिए और भी अधिक महत्वपूर्ण है) की रक्षा से ग्राहक को सुरक्षित रखें।

एक HTTPS समानता बनाने के लिए, (1) क्लासिक सर्वर प्रमाणपत्र है, (2) आमतौर पर उपयोगकर्ता के लिए उपयोगकर्ता नाम/पासवर्ड है। लेकिन थ्रिफ्ट एसएसएल के साथ, हम ग्राहक को प्रमाण पत्र जारी करके पारस्परिक प्रमाणीकरण प्राप्त करेंगे।

मेरे द्वारा किए गए उदाहरण स्व-हस्ताक्षरित प्रमाणपत्र का उपयोग करेंगे। उन्हें आसानी से openssl द्वारा प्रबंधित मिनी सीए में अनुकूलित किया जा सकता है, और मैं इसे पाठक के लिए एक अभ्यास के रूप में छोड़ देता हूं।

सर्वर निजी कुंजी जनरेट करें:
openssl genrsa -out server-key.pem 2048

संबद्ध सार्वजनिक कुंजी और उत्पन्न यह स्व-हस्ताक्षरित:
openssl genrsa -out client-key.pem 2048

जनरेट करें:
openssl req -new -x509 -key server-key.pem -out server-cert.pem -days 10000

ग्राहक निजी कुंजी उत्पन्न संबंधित सार्वजनिक कुंजी और स्वयं साइन इन करें:
openssl req -new -x509 -key client-key.pem -out client-cert.pem -days 10000

नोट: जब openssl req"Common Name (e.g. server FQDN or YOUR name)" के लिए पूछता है, तो मेजबान का FQDN डालें जिस पर थ्रिफ्ट प्रोग्राम चलाएगा। यह थ्रिफ्ट की AccessManager कक्षा को अनुकूलित करने की अनुमति नहीं देगा। यदि दूसरी तरफ एफक्यूडीएन अग्रिम में नहीं जानी जा सकती है, तो उसे AccessManager का उत्तराधिकारी होना चाहिए और तदनुसार verify() विधियों को ओवरराइड करना होगा। TSSLSocket.cpp देखें।

अच्छा, अब कोड के लिए।

सर्वर साइड पर:

socketFactory->server(true); अनावश्यक है, इसे हटाने।

socketFactory->authenticate(false) थोड़ा भ्रामक है। एक बेहतर नाम authenticatePeer होगा। यदि आप false कहते हैं, तो यह क्लाइंट को प्रमाणित नहीं करेगा, लेकिन हम पारस्परिक प्रमाणीकरण चाहते हैं इससे पहले हमने फैसला किया था।

तो, एक सर्वर के लिए एक एसएसएल प्रस्तावना है:

try { 
    signal(SIGPIPE, SIG_IGN); // See README.SSL 
    shared_ptr<TSSLSocketFactory> sslSocketFactory(new TSSLSocketFactory()); 
    sslSocketFactory->loadPrivateKey(myKey); 
    sslSocketFactory->loadCertificate(myCert); 
    sslSocketFactory->authenticate(true); 
    sslSocketFactory->loadTrustedCertificates(trustedCerts); 
    sslSocketFactory->ciphers("HIGH:!DSS:[email protected]"); 
    ... 
    } catch (TException& tx) { 
     .... 
    } 

कहाँ myKeyserver-key.pem है, myCertserver-cert.pem है और trustedCerts है ... या तो एक विश्वस्त CA का प्रमाणपत्र, या एक आत्म के मामले में, हस्ताक्षर प्रमाण, ग्राहक का प्रमाण। आप cat एक ही फ़ाइल में एक के बाद एक से अधिक certs कर सकते हैं। हमारे उदाहरण में, हम client-cert.pem डाल देंगे जिसे हमने पहले बनाया था।

ग्राहक के लिए एक एसएसएल प्रीम्बल सही क्लाइंट निजी कुंजी, क्लाइंट प्रमाण और trustedCerts के लिए, पीयर का प्रमाण है: server-cert.pem जिसे हमने पहले बनाया था।

यह सब कुछ है :-) कोड को कूदने से पहले समझने की कोशिश करें, अगर आपके पास एसएसएल (पारस्परिक) प्रमाणीकरण कैसे काम करता है, इसकी स्पष्ट तस्वीर नहीं है, तो त्रुटि संदेशों को समझना मुश्किल है। मैंने जो कोड दिखाया है वह काम करने के लिए परीक्षण किया जाता है।

दस्तावेज़ीकरण के अनुसार, दुर्भाग्य से बहाव कुछ भी नहीं है। एसएसएल के लिए, आप देख सकते हैं: lib/cpp/README.SSL, test/cpp/src/TestServer.cpp और test/cpp/src/TestClient.cpp। चेतावनी दीजिये कि TestServer.cpp आपसी प्रमाणीकरण नहीं करता है, जो एक त्रुटि IMHO है।