How to get a certificate from special C # binding

I found on the Internet only a way to get all certificates from iis, and I do it as follows (C #):

var store = new X509Store(StoreName.My, StoreLocation.LocalMachine); store.Open(OpenFlags.ReadOnly); store.Certificates; 

Now I'm trying to get a specific certificate of a specific binding, how can I do this in C #?

+5
source share
3 answers

The certificates themselves do not contain absolutely any information about the bindings used in IIS, so you cannot get certificates from the computer and expect them to have something related to IIS. You will need to request this information from IIS.

To do this, you need to add a link to the library, which is located in %windir%\system32\inetsrv\Microsoft.Web.Administration.dll (note: IIS 7 or later must be installed). After that, you can do something like the following to get the certificate:

 ServerManager manager = new ServerManager(); Site yourSite = manager.Sites["yourSiteName"]; X509Certificate2 yourCertificate = null; foreach (Binding binding in yourSite.Bindings) { if (binding.Protocol == "https" && binding.EndPoint.ToString() == "127.0.0.1" /*your binding IP*/) { var store = new X509Store(StoreName.My, StoreLocation.LocalMachine); store.Open(OpenFlags.ReadOnly); yourCertificate = store.Certificates.Find(X509FindType.FindByThumbprint, ToHex(binding.CertificateHash), true)[0]; break; } } public static string ToHex(byte[] ba) { var hex = new StringBuilder(ba.Length * 2); foreach (byte b in ba) { hex.AppendFormat("{0:x2}", b); } return hex.ToString(); } 
+6
source

I think Camilo has a little problem. As far as I can see (tested it), the code to search for the certificate does not work, because System.Convert.ToBase64String(binding.CertificateHash) does not return a valid fingerprint of the certificate.

My version:

  /// <summary> /// Returns the https certificate used for a given local IIS website. /// </summary> /// <param name="sWebsite">Website url, eg, "https://myserver.company.com"</param> /// <returns>certificate, null if not found</returns> private X509Certificate2 FindIisHttpsCert(string sWebsite) { Uri uriWebsite = new Uri(sWebsite); using (ServerManager sm = new ServerManager()) { string sBindingPort = string.Format(":{0}:", uriWebsite.Port); Binding bdBestMatch = null; foreach (Site s in sm.Sites) { foreach (Binding bd in s.Bindings) { if (bd.BindingInformation.IndexOf(sBindingPort) >= 0) { string sBindingHostInfo = bd.BindingInformation.Substring(bd.BindingInformation.LastIndexOf(':') + 1); if (uriWebsite.Host.IndexOf(sBindingHostInfo, StringComparison.InvariantCultureIgnoreCase) == 0) { if ((bd.Protocol == "https") && ((bdBestMatch == null) || (bdBestMatch.BindingInformation.Length < bd.BindingInformation.Length))) bdBestMatch = bd; } } } } if (bdBestMatch != null) { StringBuilder sbThumbPrint = new StringBuilder(); for (int i = 0; i < bdBestMatch.CertificateHash.Length; i++) sbThumbPrint.AppendFormat("{0:X2}", bdBestMatch.CertificateHash[i]); X509Store store = new X509Store(bdBestMatch.CertificateStoreName, StoreLocation.LocalMachine); store.Open(OpenFlags.ReadOnly); X509Certificate2Collection coll = store.Certificates.Find(X509FindType.FindByThumbprint, sbThumbPrint.ToString(), true); if (coll.Count > 0) return coll[0]; } } return null; // if no matching site was found } 

This function also works if several https sites are hosted on the same server (verified) and should work if the site uses a port other than 443 (not tested). To get the binding information, %windir%\system32\inetsrv\Microsoft.Web.Administration.dll , as in Camilo's answer.

+4
source

The following link should help:

basically store.Certificates returns a collection of all certificates in a particular store, then you can search for the one you need. The link shows how to do this if you know the name of the subject of the certificate that you want.

How to get X509 certificate from certificate store and generate xml signature data?

-1
source

Source: https://habr.com/ru/post/1239578/


All Articles