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.)