【问题标题】:C# Enumerate all hostnames supported by TLS certificatesC# 枚举 TLS 证书支持的所有主机名
【发布时间】:2016-03-24 09:16:30
【问题描述】:

我一直在使用System.Security.Cryptography.X509Certificates.X509Store 枚举机器上的所有 TLS 证书(在代码中验证重定向到 SSL 是否有效,并在证书丢失时发出警告)。我有以下列表功能,可以帮助我诊断像我现在遇到的问题,但我似乎找不到我需要的数据:

        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();

由于希望在同一 IP 地址上支持新的备用主机名,我们最近转而使用具有多个主机的 UCC 证书。不幸的是,上面的代码似乎无法看到证书“主题备用名称”字段中指定的任何备用主机名(一个 UCC 证书用于指定多个主机),而且我找不到让我可以访问这些数据的属性或函数。

简而言之,有谁知道如何使用 C# 从本地安装证书的“主题备用名称”字段中获取支持的主机名列表?

【问题讨论】:

    标签: c# ssl x509 x509certificate2


    【解决方案1】:

    不是作为一个单独的列表,而是作为一个单独的列表——只需找到主题备用名称扩展名并调用.Format(bool multiLine) 方法:

    var sanNames = String.Empty;
    var san = mCert.Extensions["2.5.29.17"];
    if (san != null) {
        sanNames = san.Format(false);
    }
    if (!String.IsNullOrEmpty(sanNames)) {// write sanNames variable to XML}
    

    詹姆斯编辑:这是完整的修改:

                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
                    }
                }
    

    【讨论】:

    • 你真的是加密货币的家伙!非常感谢!
    • 神奇的2.5.29.17 ip 地址是怎么回事?这是哪里来的?
    • @Brondahl 这不是一个 IP 地址,它是一个 OID - 请参阅 oid-info.com/get/2.5.29.17
    猜你喜欢
    • 2016-04-12
    • 1970-01-01
    • 2012-10-30
    • 2010-09-11
    • 1970-01-01
    • 2018-11-05
    • 2011-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多