Как вы анализируете альтернативные имена субъекта из X509Certificate2?

есть ли простой способ получить альтернативные имена субъекта из объекта X509Certificate2?

        foreach (X509Extension ext in certificate.Extensions)
        {
            if (ext.Oid.Value.Equals(/* SAN OID */"2.5.29.17"))
            {
                byte[] raw = ext.RawData;
                // ?????? parse to get type and name ????????
            }
        }

4 ответов


использовать способ формате расширения для печати версия.

X509Certificate2 cert = /* your code here */;

foreach (X509Extension extension in cert.Extensions)
{
    // Create an AsnEncodedData object using the extensions information.
    AsnEncodedData asndata = new AsnEncodedData(extension.Oid, extension.RawData);
    Console.WriteLine("Extension type: {0}", extension.Oid.FriendlyName);
    Console.WriteLine("Oid value: {0}",asndata.Oid.Value);
    Console.WriteLine("Raw data length: {0} {1}", asndata.RawData.Length, Environment.NewLine);
    Console.WriteLine(asndata.Format(true));
}

чтобы получить "альтернативное имя субъекта" сертификата:

X509Certificate2 cert = /* your code here */;

Console.WriteLine("UpnName : {0}{1}", cert.GetNameInfo(X509NameType.UpnName, false), Environment.NewLine);

Я создал функцию для этого:

private static List<string> ParseSujectAlternativeName(X509Certificate2 cert)
{
            var result = new List<string>();

            var subjectAlternativeName = cert.Extensions.Cast<X509Extension>()
                                                .Where(n => n.Oid.FriendlyName.EqualsCase(SubjectAlternativeName))
                                                .Select(n => new AsnEncodedData(n.Oid, n.RawData))
                                                .Select(n => n.Format(true))
                                                .FirstOrDefault();

            if (subjectAlternativeName != null)
            {
                var alternativeNames = subjectAlternativeName.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);

                foreach (var alternativeName in alternativeNames)
                {
                    var groups = Regex.Match(alternativeName, @"^DNS Name=(.*)").Groups;

                    if (groups.Count > 0 && !String.IsNullOrEmpty(groups[1].Value))
                    {
                        result.Add(groups[1].Value);
                    }
                }
            }

            return result;           
}

на основе ответа от Minh, вот автономная статическая функция, которая должна вернуть их все

    public static IEnumerable<string> ParseSujectAlternativeNames(X509Certificate2 cert)
    {
        Regex sanRex = new Regex(@"^DNS Name=(.*)", RegexOptions.Compiled | RegexOptions.CultureInvariant);

        var sanList = from X509Extension ext in cert.Extensions
                      where ext.Oid.FriendlyName.Equals("Subject Alternative Name", StringComparison.Ordinal)
                      let data = new AsnEncodedData(ext.Oid, ext.RawData)
                      let text = data.Format(true)
                      from line in text.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
                      let match = sanRex.Match(line)
                      where match.Success && match.Groups.Count > 0 && !string.IsNullOrEmpty(match.Groups[1].Value)
                      select match.Groups[1].Value;

        return sanList;
    }