Recuerda que en la informática cualquier problema suele tener varias soluciones, de igual modo aquí compartiremos lo más óptimo y eficiente.
Solución:
Los certificados en sí mismos no contienen absolutamente ninguna información sobre los enlaces utilizados en IIS, por lo que no puede recuperar los certificados de la máquina y esperar que tengan algo relacionado con IIS. Tendría que consultar esa información de IIS.
Para hacer esto, deberá agregar una referencia a la biblioteca que se puede encontrar en %windir%system32inetsrvMicrosoft.Web.Administration.dll
(nota: se debe instalar IIS 7 o posterior). Después de esto, puede hacer algo como lo siguiente para obtener el certificado:
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();
Creo que la respuesta de Camilo tiene un pequeño problema. Por lo que puedo ver (probado) el código para encontrar el certificado no funciona, porque System.Convert.ToBase64String(binding.CertificateHash)
no devuelve una huella digital de certificado válida.
Mi version:
///
/// Returns the https certificate used for a given local IIS website.
///
/// Website url, e.g., "https://myserver.company.com"
/// certificate, null if not found
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)
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
Esta función también funciona si varios sitios https están alojados en el mismo servidor (probado) y debería funcionar si el sitio usa un puerto diferente al 443 (no probado). Para obtener información vinculante, %windir%system32inetsrvMicrosoft.Web.Administration.dll
se usa, como en la respuesta de Camilo.