Get X509Certificate2 from a LDAP Server or Remote Machine

In Scenario1 I blogged how to get Certificate using the X509Store Class. Where I used something like this.

X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);

But after spending a bit of time with the X509Store I realized it has limitations. The StoreLoacation enum has only 2 options:

  • CurrentUser: The X.509 certificate store used by the current user.
  • LocalMachine: The X.509 certificate store assigned to the local machine. 

But I wanted to Load Certificate from a Remote LDAP Server...

I googled a bit but did not find any solutions to use the X509Store to Load Certificates from a remote machine. Then I used System.DirectoryServices namespace, SearchResult Class and DirectorySearcher Class to do the same. All I had to do is to use the DirectorySearcher and define SearchScope and create a Filter to find the desired Certificate from the remote machine. Then I imported the Certificate into X509Certificate2 using the handy Import Method. And the code looks like this.

[WebMethod]
public byte[] GetRecipientCertificateFromLDAPStore()
{
SearchResultCollection col;
DirectorySearcher searcher = new DirectorySearcher();
string[] resultsFields = new string[] { "cn", "mail", "usercertificate;binary" };
//Pass the IPAddress and the Port of the LDAP Server.
string[] textArray1 = new string[] { "LDAP://", "103.20.218.16", ":", "180", "/c=blabla" };
searcher.SearchRoot = new DirectoryEntry(string.Concat(textArray1), null, null, AuthenticationTypes.None);
searcher.SearchScope = SearchScope.Subtree;
searcher.PropertiesToLoad.AddRange(resultsFields);
searcher.Filter =string.Format("(&(cn={0})(mail={1}))", "* *", emailAddress);
col = searcher2.FindAll();


X509Certificate2 certificate1 = new X509Certificate2();
foreach (SearchResult result1 in col)
{
  IEnumerator enumerator2;
  try
  {
    enumerator2 = result1.GetDirectoryEntry().Properties["usercertificate;binary"].GetEnumerator();
    while (enumerator2.MoveNext())
    {
      object obj1 = RuntimeHelpers.GetObjectValue(enumerator2.Current);
      certificate1.Import((byte[])obj1);
      //Can access different Properties for example:
      //certificate1.Subject;
      //
certificate1.SerialNumber;
      //certificate1.Version;
      //certificate1.NotBefore;
      //certificate1.NotAfter;
      //certificate1.Issuer;
      
      return certificate1.Export(X509ContentType.Cert);

    }
  }
  catch{....}

}

return null;

}


I have seen approaches where CAPICOM has been used to import certificates from remote machine. But that creates dependency on COM. I wanted to stick to Managed code and to use the new X509Certificate2 that ships with .Net Framework 2.0.

(Please Note: If anyone know a different better approach please let me know.)

Published Sun, Mar 11 2007 4:50 by shahed
Powered by Community Server (Commercial Edition), by Telligent Systems