2011-05-23 11 views
6

मेरे कार्यक्रम में 2 रूट कर्र्ट हैं जिन्हें मैं जानता हूं और भरोसा करता हूं। मुझे ट्रस्टेंटर्स द्वारा जारी ट्रस्टेंटर्स और "उपयोगकर्ता" कर्टों के कैर्ट को सत्यापित करना होगा, जो सभी इन 2 रूट कर्ट से उत्पन्न होते हैं।रूट प्रमाणपत्र आयात किए बिना X509 प्रमाण पत्र को कैसे सत्यापित करें?

मैं सत्यापित करने के लिए X509Chain क्लास का उपयोग करता हूं लेकिन यह केवल तभी काम करता है जब रूट प्रमाणपत्र विंडोज प्रमाणपत्र स्टोर में है।

मैं थिस रूट रूट्स आयात किए बिना कर्ट को सत्यापित करने का एक तरीका ढूंढ रहा हूं - किसी भी तरह X509Chain क्लास को बताएं कि मुझे इस रूट कर्ट पर भरोसा है और इसे केवल श्रृंखला में केवल कर्टों की जांच करनी चाहिए और कुछ भी नहीं।

वास्तविक कोड:

 X509Chain chain = new X509Chain(); 
     chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; 
     chain.ChainPolicy.ExtraStore.Add(root); // i do trust this 
     chain.ChainPolicy.ExtraStore.Add(trust); 
     chain.Build(cert); 

संपादित करें: यह एक .NET 2.0 Winforms आवेदन है।

उत्तर

1

इसे प्राप्त करने का तरीका कस्टम सत्यापन लिखना होगा।

आप एक WCF संदर्भ इस System.IdentityModel.Selectors.X509CertificateValidator उपवर्गीकरण और web.config में serviceBehavior वस्तु पर कस्टम मान्यता निर्दिष्ट करके किया जाता में हैं:

<serviceBehaviors> 
    <behavior name="IdentityService"> 
     <serviceMetadata httpGetEnabled="true" /> 
     <serviceDebug includeExceptionDetailInFaults="true" /> 
     <serviceCredentials> 
     <clientCertificate> 
      <authentication customCertificateValidatorType="SSOUtilities.MatchInstalledCertificateCertificateValidator, SSOUtilities" 
      certificateValidationMode="Custom" /> 
     </clientCertificate> 
     <serviceCertificate findValue="CN=SSO ApplicationManagement" 
      storeLocation="LocalMachine" storeName="My" /> 
     </serviceCredentials> 
    </behavior> 

लेकिन अगर आप एक तरह से स्वीकार करने के लिए देख रहे हैं एसएसएल प्रमाणपत्र एक और मेजबान से आप web.config फ़ाइल में system.net सेटिंग्स को संशोधित कर सकते हैं:

नीचे X509CertificateValidator का एक उदाहरण है जो परीक्षण करता है कि क्लाइंट प्रमाणपत्र स्थानीयमाचिन/पर्सनल स्टोर में मौजूद है या नहीं। (जो कि तुम क्या जरूरत नहीं है, लेकिन एक उदाहरण के रूप में उपयोगी हो सकता है।

using System.Collections.Generic; 
using System.Linq; 
using System.Security; 
using System.Security.Cryptography.X509Certificates; 

/// <summary> 
/// This class can be injected into the WCF validation 
/// mechanism to create more strict certificate validation 
/// based on the certificates common name. 
/// </summary> 
public class MatchInstalledCertificateCertificateValidator 
    : System.IdentityModel.Selectors.X509CertificateValidator 
{ 
    /// <summary> 
    /// Initializes a new instance of the MatchInstalledCertificateCertificateValidator class. 
    /// </summary> 
    public MatchInstalledCertificateCertificateValidator() 
    { 
    } 

    /// <summary> 
    /// Validates the certificate. Throws SecurityException if the certificate 
    /// does not validate correctly. 
    /// </summary> 
    /// <param name="certificateToValidate">Certificate to validate</param> 
    public override void Validate(X509Certificate2 certificateToValidate) 
    { 
     var log = SSOLog.GetLogger(this.GetType()); 
     log.Debug("Validating certificate: " 
      + certificateToValidate.SubjectName.Name 
      + " (" + certificateToValidate.Thumbprint + ")"); 

     if (!GetAcceptedCertificates().Where(cert => certificateToValidate.Thumbprint == cert.Thumbprint).Any()) 
     { 
      log.Info(string.Format("Rejecting certificate: {0}, ({1})", certificateToValidate.SubjectName.Name, certificateToValidate.Thumbprint)); 
      throw new SecurityException("The certificate " + certificateToValidate 
       + " with thumprint " + certificateToValidate.Thumbprint 
       + " was not found in the certificate store"); 
     } 

     log.Info(string.Format("Accepting certificate: {0}, ({1})", certificateToValidate.SubjectName.Name, certificateToValidate.Thumbprint)); 
    } 

    /// <summary> 
    /// Returns all accepted certificates which is the certificates present in 
    /// the LocalMachine/Personal store. 
    /// </summary> 
    /// <returns>A set of certificates considered valid by the validator</returns> 
    private IEnumerable<X509Certificate2> GetAcceptedCertificates() 
    { 
     X509Store k = new X509Store(StoreName.My, StoreLocation.LocalMachine); 

     try 
     { 
      k.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); 
      foreach (var cert in k.Certificates) 
      { 
       yield return cert; 
      } 
     } 
     finally 
     { 
      k.Close(); 
     } 
    } 
} 
+0

मैंने सवाल संपादित किया है, यह एक .NET 2.0 विनफॉर्म एप्लिकेशन है। – RainerM

1

क्या आप जानते हैं जो प्रमाण पत्र प्रमाण पत्र की जांच करने के लिए, यदि आपके पास रूट और मध्यवर्ती की सार्वजनिक कुंजी लोड कर सकते हैं जड़ और मध्यवर्ती प्रमाणपत्र हो सकता है तो X509Chain वस्तु की ChainPolicy.ExtraStore संग्रह में प्रमाणपत्र।

मेरे कार्य भी एक Windows एक प्रमाण पत्र स्थापित करने के लिए फॉर्म्स आवेदन, केवल अगर यह मेरे देश की सरकार के नाम से जाना जाता "राष्ट्रीय रूट प्रमाणपत्र" पर निर्भर जारी किया गया था लिखने के लिए वहाँ भी था। सीए की एक सीमित संख्या है जिसे राष्ट्रीय वेब सेवाओं के कनेक्शन प्रमाणित करने के लिए प्रमाण पत्र जारी करने की अनुमति है, इसलिए मेरे पास एक था प्रमाणपत्र में सीमित सेट जो श्रृंखला में हो सकता है और लक्ष्य मशीन पर गायब हो सकता है। मैं आवेदन की एक उप-निर्देशिका "प्रमाणपत्र" में सीए के के सभी सार्वजनिक कुंजी और सरकारी रूट प्रमाणपत्र एकत्र: chain certificates

दृश्य स्टूडियो में, मैं समाधान के लिए निर्देशिका प्रमाणपत्र जोड़ा गया है और के रूप में एम्बेडेड इस निर्देशिका में सभी फ़ाइलों को चिह्नित संसाधन। यह मुझे मेरे सी # लाइब्रेरी कोड में "विश्वसनीय" प्रमाणपत्रों के संग्रह की गणना करने की अनुमति देता है, प्रमाण पत्र जांचने के लिए एक श्रृंखला बनाने के लिए, भले ही जारीकर्ता प्रमाणपत्र स्थापित नहीं है।मैं इस उद्देश्य के लिए X509Chain के लिए एक आवरण वर्ग बनाया:

private class X509TestChain : X509Chain, IDisposable 
{ 
    public X509TestChain(X509Certificate2 oCert) 
    : base(false) 
    { 
    try 
    { 
     ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; 
     ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; 
     if (!Build(oCert) || (ChainElements.Count <= 1)) 
     { 
     Trace.WriteLine("X509Chain.Build failed with installed certificates."); 
     Assembly asmExe = System.Reflection.Assembly.GetEntryAssembly(); 
     if (asmExe != null) 
     { 
      string[] asResources = asmExe.GetManifestResourceNames(); 
      foreach (string sResource in asResources) 
      { 
      if (sResource.IndexOf(".cert.") >= 0) 
      { 
       try 
       { 
       using (Stream str = asmExe.GetManifestResourceStream(sResource)) 
       using (BinaryReader br = new BinaryReader(str)) 
       { 
        byte[] abResCert = new byte[str.Length]; 
        br.Read(abResCert, 0, abResCert.Length); 
        X509Certificate2 oResCert = new X509Certificate2(abResCert); 
        Trace.WriteLine("Adding extra certificate: " + oResCert.Subject); 
        ChainPolicy.ExtraStore.Add(oResCert); 
       } 
       } 
       catch (Exception ex) 
       { 
       Trace.Write(ex); 
       } 
      } 
      } 
     } 
     if (Build(oCert) && (ChainElements.Count > 1)) 
      Trace.WriteLine("X509Chain.Build succeeded with extra certificates."); 
     else 
      Trace.WriteLine("X509Chain.Build still fails with extra certificates."); 
     } 
    } 
    catch (Exception ex) 
    { 
     Trace.Write(ex); 
    } 
    } 

    public void Dispose() 
    { 
    try 
    { 
     Trace.WriteLine(string.Format("Dispose: remove {0} extra certificates.", ChainPolicy.ExtraStore.Count)); 
     ChainPolicy.ExtraStore.Clear(); 
    } 
    catch (Exception ex) 
    { 
     Trace.Write(ex); 
    } 
    } 
} 

बुला समारोह में, मैं अब सफलतापूर्वक जांच कर सकता है एक अज्ञात प्रमाणपत्र राष्ट्रीय मूल प्रमाणपत्र से निकला है, तो:

bool bChainOK = false; 
    using (X509TestChain oChain = new X509TestChain(oCert)) 
    { 
     if ((oChain.ChainElements.Count > 0) 
     && IsPKIOverheidRootCert(oChain.ChainElements[oChain.ChainElements.Count - 1].Certificate)) 
     bChainOK = true; 
     if (!bChainOK) 
     { 
     TraceChain(oChain); 
     sMessage = "Root certificate not present or not PKI Overheid (Staat der Nederlanden)"; 
     return false; 
     } 
    } 
    return true; 

तस्वीर को पूरा करने के लिए : रूट प्रमाणपत्र की जांच करने के लिए (आमतौर पर यह स्थापित किया जाता है क्योंकि यह विंडोज अपडेट में शामिल है, लेकिन सिद्धांत में भी गायब हो सकता है), मैं दोस्ताना नाम और थंबप्रिंट की तुलना प्रकाशित मूल्यों से करता हूं:

private static bool IsPKIOverheidRootCert(X509Certificate2 oCert) 
{ 
    if (oCert != null) 
    { 
    string sFriendlyName = oCert.FriendlyName; 
    if ((sFriendlyName.IndexOf("Staat der Nederlanden") >= 0) 
     && (sFriendlyName.IndexOf(" Root CA") >= 0)) 
    { 
     switch (oCert.Thumbprint) 
     { 
     case "101DFA3FD50BCBBB9BB5600C1955A41AF4733A04": // Staat der Nederlanden Root CA - G1 
     case "59AF82799186C7B47507CBCF035746EB04DDB716": // Staat der Nederlanden Root CA - G2 
     case "76E27EC14FDB82C1C0A675B505BE3D29B4EDDBBB": // Staat der Nederlanden EV Root CA 
      return true; 
     } 
    } 
    } 
    return false; 
} 

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

3

मुझे बिल्ड विधि के परिणाम पर निर्भर नहीं होने के कारण समाधान मिला लेकिन चेनस्टैटस संपत्ति की जांच करने के लिए इसका समाधान मिला। (.NET 2.0 पर परीक्षण नहीं लेकिन यह एकमात्र समाधान मैं इस आम समस्या के लिए मिल गया है है)

X509Chain chain = new X509Chain(); 
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; 
chain.ChainPolicy.ExtraStore.Add(root); 
chain.Build(cert); 
if (chain.ChainStatus.Length == 1 && 
    chain.ChainStatus.First().Status == X509ChainStatusFlags.UntrustedRoot) 
{ 
    // chain is valid, thus cert signed by root certificate 
    // and we expect that root is untrusted which the status flag tells us 
} 
else 
{ 
    // not valid for one or more reasons 
} 

यह भी प्रयोग के माध्यम से खोज की थी की स्थापना

ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; 

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

+0

ऐसा लगता है कि अंतहीन इकाई प्रमाण पर हस्ताक्षर करने के लिए उपयोग की जाने वाली रूट अलग-अलग "अविश्वसनीय रूट" भी लौटाती है। वास्तव में व्यवहार नहीं चाहता था। –

+0

मैं AllowUnknownCertificateAuthority के बारे में आपकी टिप्पणियों से सहमत हूं, मैं एक्स्ट्रास्टोर में अपना स्वयं का सीए कर्ट जोड़ने के दौरान स्वयं एक ही निष्कर्ष पर आया था – tul

0

मैंने सिर्फ @Tristan से कोड को चेक के साथ बढ़ाया है कि रूट प्रमाणपत्र एक्स्ट्रास्टोर में जोड़े गए प्रमाणपत्रों में से एक है।

X509Chain chain = new X509Chain(); 
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; 
chain.ChainPolicy.ExtraStore.Add(root); 
chain.Build(cert); 
if (chain.ChainStatus.Length == 1 && 
    chain.ChainStatus.First().Status == X509ChainStatusFlags.UntrustedRoot && 
    chain.ChainPolicy.ExtraStore.Contains(chain.ChainElements[chain.ChainElements.Count - 1].Certificate)) 
{ 
    // chain is valid, thus cert signed by root certificate 
    // and we expect that root is untrusted which the status flag tells us 
    // but we check that it is a known certificate 
} 
else 
{ 
    // not valid for one or more reasons 
} 
संबंधित मुद्दे