2015-12-17 1 views
3

J'utilise depuis un moment déjà System.Security.Cryptography.X509Certificates.X509Store pour énumérer tous les certificats TLS sur la machine (pour valider dans le code si la redirection vers SSL fonctionnera ou pas et avertir si le certificat est manquant). J'ai la fonction liste suivante qui me permet de diagnostiquer les problèmes comme celui que je vais avoir en ce moment, mais je ne peux pas sembler trouver les données dont j'ai besoin:C# Énumérer tous les noms d'hôte pris en charge par les certificats TLS

 System.Security.Cryptography.X509Certificates.X509Store store = new System.Security.Cryptography.X509Certificates.X509Store(System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine); 

     store.Open(System.Security.Cryptography.X509Certificates.OpenFlags.ReadOnly); 

     DateTime utcNow = DateTime.UtcNow; 
     foreach (System.Security.Cryptography.X509Certificates.X509Certificate2 mCert in store.Certificates) 
     { 
      writer.WriteStartElement("certificate"); 
      writer.WriteAttributeString("friendlyName", mCert.FriendlyName); 
      writer.WriteAttributeString("subjectName", mCert.SubjectName.Name); 
      writer.WriteAttributeString("subject", mCert.Subject); 
      writer.WriteAttributeString("simpleName", mCert.GetNameInfo(System.Security.Cryptography.X509Certificates.X509NameType.SimpleName, false)); 
      writer.WriteAttributeString("dnsName", mCert.GetNameInfo(System.Security.Cryptography.X509Certificates.X509NameType.DnsName, false)); 
      writer.WriteAttributeString("certhash", mCert.GetCertHashString()); 
      writer.WriteAttributeString("effectivedate", mCert.GetEffectiveDateString()); 
      writer.WriteAttributeString("expirationdate", mCert.GetExpirationDateString()); 
      writer.WriteAttributeString("format", mCert.GetFormat()); 
      writer.WriteAttributeString("keyalgorithm", mCert.GetKeyAlgorithm()); 
      writer.WriteAttributeString("publickey", mCert.GetPublicKeyString()); 
      writer.WriteAttributeString("serialnumber", mCert.SerialNumber); 
      writer.WriteAttributeString("hasprivatekey", XmlConvert.ToString(mCert.HasPrivateKey)); 
      writer.WriteAttributeString("issuer", mCert.Issuer); 
      // NOTE: X509Certificate2 as provided by .NET uses local datetimes, so we need to convert them to the sane choice of UTC here 
      writer.WriteAttributeString("notafterutc", XmlConvert.ToString(mCert.NotAfter.ToUniversalTime(), XmlDateTimeSerializationMode.Utc)); 
      writer.WriteAttributeString("notbeforeutc", XmlConvert.ToString(mCert.NotBefore.ToUniversalTime(), XmlDateTimeSerializationMode.Utc)); 
      writer.WriteAttributeString("validnow", XmlConvert.ToString(mCert.NotBefore.ToUniversalTime() < utcNow && utcNow < mCert.NotAfter.ToUniversalTime())); 
      writer.WriteAttributeString("timeuntilexpiration", XmlConvert.ToString(mCert.NotAfter.ToUniversalTime() - utcNow)); 
      writer.WriteAttributeString("thumbprint", mCert.Thumbprint); 
      writer.WriteAttributeString("version", mCert.Version.ToString()); 
      writer.WriteEndElement(); // certificate 
     } 
     writer.WriteEndElement(); // certificates 
     writer.WriteEndResponse(); 

En raison d'un désir de soutenir une nouvelle alternative nom d'hôte sur la même adresse IP, nous avons récemment passé à l'utilisation d'un certificat UCC avec plusieurs hôtes. Malheureusement, le code ci-dessus ne semble pas pouvoir voir les autres noms d'hôtes spécifiés dans le champ "Subject Alternative Name" du certificat (les certificats UCC utilisés pour spécifier plusieurs hôtes), et j'ai du mal à trouver un propriété ou fonction qui me donne accès à ces données. En bref, est-ce que quelqu'un sait comment obtenir la liste des noms d'hôte pris en charge à partir du champ "Subject Alternative Name" d'un certificat installé localement en utilisant C#?

Répondre

2

non comme une liste séparée, mais comme une liste unique - trouver simplement l'extension Sujet Noms alternatifs et appeler .Format(bool multiLine) méthode:

var sanNames = String.Empty; 
foreach (var ext in mCert.Extensions) { 
    if (ext.Oid.Value == "2.5.29.17") { 
     sanNames = ext.Format(false); 
    } 
} 
if (!String.IsNullOrEmpty(sanNames)) {// write sanNames variable to XML} 

EDIT Par James: Voici la modification complète:

  System.Security.Cryptography.X509Certificates.X509Extension uccSan = mCert.Extensions["2.5.29.17"]; 
      if (uccSan != null) 
      { 
       foreach (string nvp in uccSan.Format(true).Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)) 
       { 
        writer.WriteStartElement("alternateName"); 
        string[] parts = nvp.Split('='); 
        string name = parts[0]; 
        string value = (parts.Length > 0) ? parts[1] : null; 
        writer.WriteAttributeString("type", name); 
        writer.WriteAttributeString("value", value); 
        writer.WriteEndElement(); // alternateName 
       } 
      } 
+0

Vous êtes vraiment le gars crypto! Merci beaucoup! – James