2011-09-07 12 views
19

मैं सी ++ का उपयोग कर Win32 में एक SSL प्रमाणपत्र सत्यापित करना चाहता हूं। मुझे लगता है कि मैं सर्ट * एपीआई का उपयोग करना चाहता हूं ताकि मैं विंडोज सर्टिफिकेट स्टोर का लाभ प्राप्त कर सकूं। यही वह है जिसके साथ मैं आया हूं।Win32 में SSL प्रमाणपत्र सत्यापित करने का सही तरीका क्या है?

  • क्या यह सही है?
  • क्या ऐसा करने का कोई बेहतर तरीका है?
  • क्या मैं कुछ गलत कर रहा हूं?
bool IsValidSSLCertificate(PCCERT_CONTEXT certificate, LPWSTR serverName) 
{ 
    LPTSTR usages[] = { szOID_PKIX_KP_SERVER_AUTH }; 

    CERT_CHAIN_PARA params       = { sizeof(params) }; 
    params.RequestedUsage.dwType      = USAGE_MATCH_TYPE_AND; 
    params.RequestedUsage.Usage.cUsageIdentifier  = _countof(usages); 
    params.RequestedUsage.Usage.rgpszUsageIdentifier = usages; 

    PCCERT_CHAIN_CONTEXT chainContext = 0; 

    if (!CertGetCertificateChain(NULL, 
            certificate, 
            NULL, 
            NULL, 
            &params, 
            CERT_CHAIN_REVOCATION_CHECK_CHAIN, 
            NULL, 
            &chainContext)) 
    { 
     return false; 
    } 

    SSL_EXTRA_CERT_CHAIN_POLICY_PARA sslPolicy = { sizeof(sslPolicy) }; 
    sslPolicy.dwAuthType      = AUTHTYPE_SERVER; 
    sslPolicy.pwszServerName     = serverName; 

    CERT_CHAIN_POLICY_PARA policy = { sizeof(policy) }; 
    policy.pvExtraPolicyPara  = &sslPolicy; 

    CERT_CHAIN_POLICY_STATUS status = { sizeof(status) }; 

    BOOL verified = CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL, 
                 chainContext, 
                 &policy, 
                 &status); 

    CertFreeCertificateChain(chainContext); 
    return verified && status.dwError == 0; 
} 
+0

आपने इसका उल्लेख नहीं किया कि आप इसका क्या उपयोग कर रहे हैं, लेकिन हां, आम तौर पर आपको CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT पास करना चाहिए यदि आप इसे एक सामान्य HTTPS परिदृश्य में उपयोग कर रहे हैं। – EricLaw

+0

मैं मुख्य रूप से एलडीएपी सर्वर एसएसएल प्रमाण पत्र (जैसे, VERIFYSERVERCERT फ़ंक्शन के अंदर) को सत्यापित करने के लिए इसका उपयोग करना चाहता हूं। मैं क्लाइंट/सर्वर एप्लिकेशन में HTTPS सर्वर प्रमाणपत्रों को सत्यापित करने के लिए इसका उपयोग करने के बारे में सोच रहा हूं, जहां ग्राहक सर्वर के लिए अपना स्वयं का SSL प्रमाणपत्र निर्दिष्ट कर सकते हैं। – briangreenery

+0

क्या CERT_CHAIN_REVOCATION_CHECK_CHAIN ​​के बजाय CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT का उपयोग करना अधिक आम है? आप निरसन के लिए रूट प्रमाणपत्र क्यों नहीं देखेंगे? – briangreenery

उत्तर

1

मुझे लगता है कि सबसे अच्छा जवाब आप क्या करने की कोशिश कर रहे हैं कि वास्तव में क्या पर निर्भर करता है।

मैं आपको चेतावनी दूंगा कि एसएसएल इस धारणा पर आधारित है कि दोनों एंडपॉइंट्स एक सुरक्षित कनेक्शन चाहते हैं। यदि कोई एंडपॉइंट सुरक्षा बनाए रखने में रूचि नहीं रखता है तो कोई भी नहीं है।

आपके वितरित कोड में बाइट कोड डालने का यह एक छोटा सा प्रयास है जो इस फ़ंक्शन के लिए बस सच है। यही कारण है कि खिड़कियों ने कर्नेल में बहुत सत्यापन किया। लेकिन उन्होंने वर्चुअल हार्डवेयर पर विंडोज़ चलाने वाले लोगों की उम्मीद नहीं की थी, जो ओएस को बस छोटे के रूप में घुमाता है।

अब मान लें कि आप कुछ स्रोत से प्रमाण प्रदान करने की उम्मीद करते हैं, लेकिन यह दिखाते हुए कि उस स्रोत को विश्वसनीय स्रोत से वही जानकारी प्रदान नहीं की जा सकती है। और फिर इसे आप को सौंपो। तो आप किसी भी व्यक्ति को विशेष रूप से "सिद्ध" करने के लिए प्रमाणपत्रों पर भरोसा नहीं कर सकते हैं।

सर्टिफिकेट से प्राप्त एकमात्र सुरक्षा बाहरी संदेश को रोकने में नहीं है, अंतराल नहीं, संदेश भेजने की गोपनीयता की उल्लंघन से।

कोई अन्य उपयोग विफल होने के लिए बर्बाद हो गया है, और यह अंततः संभावित विनाशकारी परिणामों के साथ विफल हो जाएगा।

बड़ी पोस्ट के लिए खेद है। टिप्पणी खंड में एक शब्द सीमा है।

+2

इस उत्तर के लिए धन्यवाद, जबकि जानकारी में मान्य है, मैं और अधिक उम्मीद कर रहा था कि कोई यह सत्यापित कर सकता है कि ऊपर वर्णित कोड Windows क्रिप्टो एपीआई का उपयोग करके SSL उपयोग के लिए प्रमाण पत्र सत्यापित करने के संदर्भ में सही है। मैं इन मामलों में एसएसएल की सीमाओं के बारे में अच्छी तरह से अवगत हूं, लेकिन यहां मैं केवल अपने एंडपॉइंट को बिल्कुल सही बनाने के लिए वास्तव में चिंतित हूं। संदर्भ के लिए, मैं PHP कोर के लिए [इस पैच] (https://github.com/php/php-src/pull/601) पर काम कर रहा हूं - इसलिए हम किसी विशिष्ट एप्लिकेशन के बारे में चिंतित नहीं हैं, केवल यही हमारे द्वारा प्रदान किए जा रहे टूल सही हैं। – DaveRandom

14

आपको RFC3280 section 6.1 और RFC5280 section 6.1 से अवगत होना चाहिए। प्रमाण पत्र पथ मान्य करने के लिए दोनों एल्गोरिदम का वर्णन करते हैं। भले ही Win32 API आपके लिए कुछ चीजों का ख्याल रखता है, फिर भी सामान्य रूप से प्रक्रिया के बारे में जानने के लिए यह मूल्यवान हो सकता है।

इसके अलावा, यहां एक (मेरी राय में) बहुत भरोसेमंद संदर्भ है: Chromium certificate verification code

कुल मिलाकर, मुझे लगता है कि आपका कोड गलत नहीं है। लेकिन यहाँ, कुछ चीजें मैं में/परिवर्तन देखने होता है कि अगर मैं तुम्हें थे:

1. अलग सामान्य नाम मान्यता

क्रोमियम श्रृंखला से अलग से प्रमाणपत्र आम नाम सत्यापित करता है। जाहिर है, उन्होंने इसके साथ कुछ समस्याएं देखी हैं। उनके तर्क के लिए टिप्पणियां देखें:

cert_verify_proc.win.cc:731 // Certificate name validation happens separately, later, using an internal 
cert_verify_proc.win.cc:732 // routine that has better support for RFC 6125 name matching. 

2. उपयोग CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT

क्रोमियम भी CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT झंडा बजाय CERT_CHAIN_REVOCATION_CHECK_CHAIN ​​का उपयोग करता है। मैंने वास्तव में अपना कोड प्राप्त करने से पहले इसे देखना शुरू कर दिया, और यह मेरी धारणा को मजबूत करता है कि आपको CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT का उपयोग करना चाहिए।

भले ही दोनों उपर्युक्त आरएफसी निर्दिष्ट करते हैं कि एक आत्म-हस्ताक्षरित ट्रस्ट एंकर को श्रृंखला का हिस्सा नहीं माना जाता है, CertGetCertificateChain (http://msdn.microsoft.com/en-us/library/windows/desktop/aa376078(v=vs.85).aspx) के लिए प्रलेखन का कहना है कि यह संभवतः एक विश्वसनीय रूट प्रमाणपत्र के लिए एक श्रृंखला बनाता है। एक विश्वसनीय रूट प्रमाणपत्र को एक विश्वसनीय स्व-हस्ताक्षरित प्रमाणपत्र के रूप में परिभाषित किया जाता है (उसी पृष्ठ पर)।

यह संभावना को समाप्त करता है कि * EXCLUDE_ROOT गैर-रूट ट्रस्ट एंकर के लिए निरस्तीकरण जांच को छोड़ सकता है (Win32 वास्तव में ट्रस्ट-एंकरों को स्वयं हस्ताक्षरित होने की आवश्यकता है, भले ही इसे किसी भी आरएफसी द्वारा आवश्यक न हो। हालांकि यह आधिकारिक तौर पर नहीं है दस्तावेज)।

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

मैंने कुछ मंचों को किया और इस मंच पोस्ट में ठोकर खाई: http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/9f95882a-1a68-477a-80ee-0a7e3c7ae5cf/x509revocationflag-question?forum=windowssecurity। .NET उत्पाद समूह (माना जाता है) का एक सदस्य दावा करता है कि प्रकृति में झंडे समान कार्य करते हैं, यदि रूट स्वयं हस्ताक्षरित है (सिद्धांत रूप में, ENTIRE_CHAIN ​​ध्वज रद्द करने के लिए मूल प्रमाणपत्र की जांच करेगा यदि इसमें सीडीपी एक्सटेंशन शामिल है, लेकिन वह नहीं हो सकता है)।

उन्होंने यह भी * EXCLUDE_ROOT झंडा उपयोग करने के लिए है क्योंकि अन्य झंडा, एक अनावश्यक नेटवर्क अनुरोध का कारण बन सकता है, तो स्व-हस्ताक्षरित जड़ सीए सीडीपी एक्सटेंशन शामिल सिफारिश की।

दुर्भाग्य:

  • मैं दो झंडे के बीच मतभेद पर किसी भी आधिकारिक तौर पर दस्तावेज स्पष्टीकरण नहीं मिल रहा।
  • हालांकि यह संभावना है कि लिंक की गई चर्चा .NET के हुड के नीचे एक ही Win32 API ध्वज पर लागू होती है, इसकी गारंटी नहीं है।

पूरी तरह से यकीन है कि यह CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT उपयोग करने के लिए ठीक है तो मुझे खुद में थोड़ा और अधिक googled और क्रोमियम SSL प्रमाणपत्र सत्यापन कोड मैं अपने जबाब के शीर्ष पर से जुड़ा हुआ पाया।

एक अतिरिक्त बोनस के रूप में, क्रोमियम cert_verify_proc_win.cc फ़ाइल आईई सत्यापन कोड के बारे में निम्नलिखित संकेत शामिल हैं:

618: // IE passes a non-NULL pTime argument that specifies the current system 
619: // time. IE passes CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT as the 
620: // chain_flags argument. 

सुनिश्चित नहीं हैं कि वे यह जानते हैं, लेकिन इस बिंदु पर मैं का उपयोग कर सहज महसूस करता हूँ CERT_CHAIN_REVOCATION_CHECK_EXCLUDE_ROOT।

3. विभिन्न स्वीकृत प्रमाणपत्र Usages

मैंने देखा क्रोमियम भी 3 प्रमाण पत्र के बजाय प्रयोग 1 निर्दिष्ट करता है:

szOID_PKIX_KP_SERVER_AUTH, 
szOID_SERVER_GATED_CRYPTO, 
szOID_SGC_NETSCAPE 

मैं क्या गूगल के माध्यम से इकट्ठा कर सकते हैं से, अन्य उपयोगों पुराने वेब के लिए आवश्यक हो सकता है ब्राउज़र, अन्यथा वे एक सुरक्षित कनेक्शन स्थापित करने में विफल हो सकते हैं।

यदि क्रोमियम इन उपयोगों को शामिल करने के लिए उपयुक्त मानता है, तो मैं सूट का पालन करता हूं।

ध्यान दें कि यदि आप अपना कोड बदलते हैं, तो आपको पैराम्स भी सेट करना चाहिए। USAGE_MATCH_TYPE_AND के बजाय USAGE_MATCH_TYPE_OR पर RequestedUsage.dwType।

-

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

-1

फ़ंक्शन CertGetCertificateChain और CertVerifyCertificatePolicy एक साथ जाते हैं। यह हिस्सा सही है।

CertGetCertificateChain के लिए झंडा निम्नलिखित तीन में से किसी को सेट किया जा सकता आप निरस्तीकरण की जांच करना चाहते हैं:

  • CERT_CHAIN_REVOCATION_CHECK_END_CERT
  • CERT_CHAIN_REVOCATION_CHECK_CHAIN ​​
  • CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT।

उनमें से केवल एक का उपयोग किया जा सकता है, ये तीन विकल्प ORed नहीं हो सकते हैं। इन झंडे में से एक के अलावा आप विचार कर सकते हैं कि श्रृंखला कैसे बनाई जानी चाहिए; local cache या बस CRL या OCSP का उपयोग कर। इन विचारों के लिए read this link

फ़ंक्शन को निष्पादित करने में त्रुटि या अधिक यदि वापसी मान 0 है, तो इसका मतलब यह नहीं है कि प्रमाणपत्र अमान्य है, बल्कि आप ऑपरेशन करने में असमर्थ थे। त्रुटि जानकारी के लिए GetLastError() का उपयोग करें। तो झूठी वापसी का आपका तर्क गलत है, यह त्रुटि फेंकने का एक मामला है और ग्राहक कोड को यह तय करने दें कि फिर से प्रयास करें या अन्य सामान करने के लिए आगे बढ़ें।

this link में "त्रुटि वर्गीकृत" नामक एक अनुभाग है, कृपया इसे पढ़ें। असल में आपको certChainContext->TrustStatus.dwErrorStatus. Here a list of error statuses will be ORed. Please check CERT_TRUST_STATUS msdn संदर्भ देखना चाहिए। तो यहां आप अपना व्यवसाय तर्क प्राप्त कर सकते हैं। उदाहरण के लिए, यदि आपको मान की त्रुटि स्थिति (CERT_TRUST_REVOCATION_STATUS_UNKNOWN | CERT_TRUST_IS_OFFLINE_REVOCATION) मिलती है तो प्रमाणपत्र निरस्तीकरण जांच नहीं की जा सकी, आपके पास यह तय करने का विकल्प है कि आप क्या चाहते हैं (प्रमाण को जाने दें या फिर भी इसे अमान्य के रूप में चिह्नित करें)।

तो, CertVerifyCertificatePolicy पर कॉल करने से पहले आपके पास एक सत्यापन त्रुटि को त्यागने या पहले से फ़्लैग करने का विकल्प है।

यदि आप CertVerifyCertificatePolicy पर आना चुनते हैं, तो क्रोमियम कोड आपके त्रुटि वर्ग/enum पर policy_status.dwError को मैप करने के तरीके के बारे में एक अद्भुत संदर्भ है।

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

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