C#枚举TLS证书支持的所有主机名
C# Enumerate all hostnames supported by TLS certificates
我已经使用 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 证书。不幸的是,上面的代码似乎无法看到证书 "Subject Alternative Name" 字段中指定的任何备用主机名(一个 UCC 证书用于指定多个主机),而且我找不到一个属性 或使我能够访问此数据的函数。
简而言之,有谁知道如何使用 C# 从本地安装的证书的 "Subject Alternative Name" 字段中获取支持的主机名列表?
不是作为一个单独的列表,而是作为一个列表——只需找到主题备用名称扩展并调用 .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
}
}
我已经使用 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 证书。不幸的是,上面的代码似乎无法看到证书 "Subject Alternative Name" 字段中指定的任何备用主机名(一个 UCC 证书用于指定多个主机),而且我找不到一个属性 或使我能够访问此数据的函数。
简而言之,有谁知道如何使用 C# 从本地安装的证书的 "Subject Alternative Name" 字段中获取支持的主机名列表?
不是作为一个单独的列表,而是作为一个列表——只需找到主题备用名称扩展并调用 .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
}
}