2009-10-29 13 views
11

मैं अपने क्लाइंट प्रमाण पत्र का उपयोग करके वेब सेवा के खिलाफ खुद को प्रमाणित करने का प्रयास कर रहा हूं, लेकिन, कुछ कारणों से (मैं समझाता हूं), मैं स्टोर से प्रमाणपत्र लोड नहीं करना चाहता, बल्कि डिस्क से इसे पढ़ना चाहता हूं ।प्रमाण पत्र स्टोर में क्लाइंट प्रमाणपत्र का उपयोग नहीं

निम्नलिखित:

// gw is teh WebService client 
X509Certificate cert = new X509Certificate(PathToCertificate); 
_gw.ClientCertificates.Add(ClientCertificate()); 
ServicePointManager.ServerCertificateValidationCallback = (a,b,c,d) => true; 
_gw.DoSomeCall(); 

रिटर्न हमेशा 403 - सेवा के लिए मुझे अधिकृत नहीं है। लेकिन, जब मैं प्रमाण पत्र को प्रमाण पत्र में सहेजता हूं, तो यह काम करता है। (जैसा कि एमएसडीएन में बताया गया है।)

क्या प्रमाण पत्र का उपयोग स्टोर में नहीं करना संभव है?

(कारण है कि मैं खिड़कियों सेवा (ग्राहक) कभी कभी बुला वेब सेवा (सर्वर) मिला है, और समय की अनिर्दिष्ट राशि के बाद सेवा 'भूल' मेरे प्रमाण पत्र और किसी स्पष्ट कारण के साथ सर्वर के विरुद्ध को अधिकृत नहीं करता है,)

उत्तर

22

PathToCertificate किस प्रकार की फ़ाइल है? अगर यह सिर्फ एक .cer फ़ाइल है, तो इसमें प्रमाणपत्र के लिए निजी कुंजी नहीं होगी और SSL/TLS के लिए उस प्रमाणपत्र का उपयोग करने का प्रयास विफल हो जाएगा।

हालांकि, अगर आपके पास पीकेसीएस 7 या पीकेसीएस 12 फ़ाइल है जिसमें प्रमाणपत्र के लिए सार्वजनिक और निजी कुंजी शामिल है, तो आपका कोड काम करेगा (आपको अधिभार का उपयोग करने की आवश्यकता हो सकती है जो निजी कुंजी में पासवर्ड लेता है)।

इसका परीक्षण करने के लिए, मैं http://www.mono-project.com/UsingClientCertificatesWithXSP पर गया और उन निर्देशों के बाद मेरी क्लाइंट.p12 फ़ाइल बनाई। मैंने परीक्षण के लिए HttpListener का उपयोग करके एक साधारण HTTPS सर्वर भी बनाया।

तब मैं 'client.exe' में निम्नलिखित कार्यक्रम संकलित और की तरह चलाएँ:

client.exe https://<MYSSLSERVER>/ client.p12 password 

जहां client.p12 PKCS12 से पहले उत्पन्न फ़ाइल है और 'पासवर्ड' पासवर्ड मैं निजी कुंजी के लिए सेट किया गया है प्रमाणपत्र का।

using System; 
using System.IO; 
using System.Net; 
using System.Security.Cryptography.X509Certificates; 
using System.Text; 

public class HttpWebRequestClientCertificateTest : ICertificatePolicy { 

    public bool CheckValidationResult (ServicePoint sp, X509Certificate certificate, 
      WebRequest request, int error) 
    { 
      return true; // server certificate's CA is not known to windows. 
    } 

    static void Main (string[] args) 
    { 
      string host = "https://localhost:1234/"; 
      if (args.Length > 0) 
        host = args[0]; 

      X509Certificate2 certificate = null; 
      if (args.Length > 1) { 
        string password = null; 
        if (args.Length > 2) 
          password = args [2]; 
        certificate = new X509Certificate2 (args[1], password); 
      } 

      ServicePointManager.CertificatePolicy = new HttpWebRequestClientCertificateTest(); 

      HttpWebRequest req = (HttpWebRequest) WebRequest.Create (host); 
      if (certificate != null) 
        req.ClientCertificates.Add (certificate); 

      WebResponse resp = req.GetResponse(); 
      Stream stream = resp.GetResponseStream(); 
      StreamReader sr = new StreamReader (stream, Encoding.UTF8); 
      Console.WriteLine (sr.ReadToEnd()); 
    } 
} 

मुझे बताएं कि क्या आप मुझे सर्वर कोड और परीक्षण के दोनों किनारों पर उपयोग किए जाने वाले प्रमाणपत्र अपलोड करना चाहते हैं।

+0

क्या आप जानते हैं Windows .NET पर एक ही काम करने के लिए कैसे? किसी कारण से मैं इसे x509 स्टोर – galets

1

क्या आपको प्रमाणपत्र के लिए पासवर्ड चाहिए? यदि हां, तो इसके लिए कन्स्ट्रक्टर में एक फ़ील्ड है।

X509Certificate cert = new X509Certificate(PathToCertificate,YourPassword); 
2

आप

पहले ...

जब तक यह एक पासवर्ड से पहुँचा जा रहा है आपका क्लाइंट प्रमाणपत्र फ़ाइल एक निजी कुंजी नहीं हो सकते कम से कम दो समस्याओं के लिए क्षमता है ...। आपको एक पासवर्ड के साथ एक पीकेसीएस # 12 (* .pfx) प्रमाणपत्र का उपयोग करना चाहिए ताकि आपके क्लाइंट की निजी कुंजी तक पहुंच हो। प्रमाण पत्र खोलते समय आपको क्लाइंट कोड को पासवर्ड प्रदान करना होगा क्योंकि अन्य पहले ही पोस्ट कर चुके हैं।

Process p = Process.Start(
    "makecert.exe", 
    String.Join(" ", new string[] { 
     "-r",//      Create a self signed certificate 
     "-pe",//     Mark generated private key as exportable 
     "-n", "CN=" + myHostName,// Certificate subject X500 name (eg: CN=Fred Dews) 
     "-b", "01/01/2000",//  Start of the validity period; default to now. 
     "-e", "01/01/2036",//  End of validity period; defaults to 2039 
     "-eku",//     Comma separated enhanced key usage OIDs 
     "1.3.6.1.5.5.7.3.1," +// Server Authentication (1.3.6.1.5.5.7.3.1) 
     "1.3.6.1.5.5.7.3.2", //  Client Authentication (1.3.6.1.5.5.7.3.2) 
     "-ss", "my",//    Subject's certificate store name that stores the output certificate 
     "-sr", "LocalMachine",// Subject's certificate store location. 
     "-sky", "exchange",//  Subject key type <signature|exchange|<integer>>. 
     "-sp",//     Subject's CryptoAPI provider's name 
     "Microsoft RSA SChannel Cryptographic Provider", 
     "-sy", "12",//    Subject's CryptoAPI provider's type 
     myHostName + ".cer"//  [outputCertificateFile] 
    }) 
); 

दूसरा ...

: इस बनाने के लिए कई तरीके हैं, सबसे आसान निम्नलिखित कमांड लाइन का उपयोग करने के पहले प्रमाण पत्र उत्पन्न करने के लिए है, तो एमएमसी प्रमाणपत्र प्रबंधक का उपयोग प्रमाण पत्र निजी कुंजी निर्यात करने के लिए है

आपकी अगली समस्या सर्वर-साइड होने जा रही है। सर्वर को इस प्रमाणपत्र को अनुमति देना है। आपके पास सही तर्क है, लेकिन तार के गलत पक्ष पर, इस लाइन को अनुरोध को संभालने वाले वेब सर्वर पर ले जाएं। यदि आप नहीं कर सकते हैं, तो आपको 'लेना होगा'।प्रमाणपत्र 'फ़ाइल सर्वर से ऊपर बचाया और सर्वर कंप्यूटर के विश्वास सूची में जोड़ने:

ServicePointManager.ServerCertificateValidationCallback = (a,b,c,d) => true; 
+0

-1 में प्रमाण पत्र पंजीकृत किए बिना कार्य नहीं कर सकता। सर्वर को क्लाइंट प्रमाणपत्र की निजी कुंजी जानने की आवश्यकता नहीं है। इसे केवल उस सीए पर विश्वास करने की आवश्यकता है जिसने क्लाइंट प्रमाण पत्र पर हस्ताक्षर किए हैं। एसएसएल 3/टीएलएस पर बातचीत करते समय, सर्वर सभी सीए के डीएन के साथ एक सूची भेजता है। उस बिंदु पर ग्राहक को क्लाइंट प्रमाण का सीए देखना चाहिए। सूची में है और इसे भेजें। – Gonzalo

+0

सही, मैंने कभी नहीं कहा कि सर्वर को निजी कुंजी की आवश्यकता है। इसे प्रमाण पत्र पर भरोसा करना चाहिए या स्पष्ट रूप से कोड के साथ अनुमति देना चाहिए। आपकी बाकी की टिप्पणी के लिए "... सर्वर सभी सीएएस के डीएन के साथ एक सूची भेजता है ..." यह सच नहीं है। –

+1

सच नहीं है? Http://tools.ietf.org/html/rfc5246#page-53, सेक्शन 7.4.4 देखें: प्रमाणपत्र_अधिकारी स्वीकार्य प्रमाणपत्र_अधिकृतताओं के विशिष्ट नाम [X501] की सूची, जो डीईआर-एन्कोडेड प्रारूप में दर्शाती है। ये विशिष्ट नाम रूट सीए या अधीनस्थ सीए के लिए वांछित विशिष्ट नाम निर्दिष्ट कर सकते हैं; इस प्रकार, इस संदेश का उपयोग पर ज्ञात जड़ों के साथ-साथ वांछित प्राधिकरण स्थान का वर्णन किया जा सकता है। यदि प्रमाणपत्र_अधिकृतता सूची खाली है, तो क्लाइंट मई उपयुक्त क्लाइंट प्रमाणपत्र प्रमाणपत्र टाइप करें, unles – Gonzalo

2

संभावित समस्या एसएसएल सत्र (Schannel कैश) की कैशिंग हो सकता है। केवल पहला अनुरोध एसएसएल हैंडशेक पर बातचीत करता है। बाद के अनुरोध एक ही सत्र आईडी का उपयोग करेंगे और आशा करते हैं कि सर्वर इसे स्वीकार करेगा। यदि सर्वर सत्र आईडी को साफ़ करता है, तो अनुरोध 403 त्रुटि के साथ विफल हो जाएंगे। स्थानीय ssl सत्र कैशिंग को अक्षम (और प्रत्येक अनुरोध के लिए एसएसएल बातचीत के लिए मजबूर) आप विंडो खोलने के लिए रजिस्ट्री फ़ोल्डर है:

[HKEY_LOCAL_MACHINE] [सिस्टम] [CurrentControlSet] [नियंत्रण] [SecurityProviders] [Schannel]

और मूल्य के साथ ClientCacheTime (DWORD) नामक कुंजी जोड़ने 0.

यह समस्या यहाँ कवर किया जाता है:

http://support.microsoft.com/?id=247658

+0

यह बहुत बड़ा है। यदि आप इसे नहीं जानते हैं, तो आप बहुत समय व्यतीत कर सकते हैं कि आप अपने "परीक्षण और त्रुटि" समाधान को अपने सबसे सरल रूप में कम कर रहे हैं, जबकि असल में चीजों को तोड़कर। – Chazt3n

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