简体   繁体   English

如何使用 BouncyCastle 检索 X509 证书的 CN 名称

[英]How to retrieve the CN name of an X509 certificate with BouncyCastle

I have a number of PEM files for domain certificates.我有许多域证书的 PEM 文件。 I've already found out how to read the single PEM objects from a file and I can tell apart certificates from private keys.我已经了解了如何从文件中读取单个 PEM 对象,并且可以将证书与私钥区分开来。 Now I need to know the subject name for each certificate I find.现在我需要知道我找到的每个证书的主题名称。 Unfortunately, there doesn't seem to exist any documentation and I wasn't able to find other users on the web who talked about doing this.不幸的是,似乎不存在任何文档,而且我无法在 web 上找到其他谈论这样做的用户。 Most code that I found was about Java and used names that are not available in the current library (for C# at least).我发现的大多数代码都是关于 Java 并使用了当前库中不可用的名称(至少对于 C#)。 Whether it's an exotic task to read CN values from a certificate or not, I need to do it.无论从证书中读取 CN 值是否是一项奇特的任务,我都需要这样做。

Here's what I found so far:这是我到目前为止发现的:

Install the NuGet package Portable.BouncyCastle 1.8.8安装 NuGet package Portable.BouncyCastle 1.8.8

using (var streamReader = new StreamReader("cert.pem"))
{
    var pemReader = new PemReader(streamReader);
    while (true)
    {
        object pemObject = pemReader.ReadObject();
        if (pemObject == null)
            break;
        switch (pemObject)
        {
            case RsaPrivateCrtKeyParameters privateKey:
                Console.WriteLine("Private key");
                break;
            case X509Certificate certificate:
                Console.WriteLine("Certificate");
                // This has ALL entries from the subject, including CN
                Console.WriteLine("  Subject: " + certificate.SubjectDN);

                // This is a convoluted list of lists of lists of stuff that seems to contain
                // the CN values somewhere deep within but I can't figure out how to access it
                var derSequence = certificate.SubjectDN.ToAsn1Object() as DerSequence;
                // And I'm not sure if these are the correct types to use and what other
                // types to be prepared for in real life.

                // Like the below untyped list of untyped lists of stuff seems to be working
                // to extract the alternative names (SAN) from a certificate:
                var altNames = certificate.GetSubjectAlternativeNames()?
                    .OfType<System.Collections.ArrayList>()
                    .SelectMany(l => l.OfType<string>())
                    .ToList();
                if (altNames != null)
                {
                    foreach (string str in altNames)
                    {
                        Console.WriteLine("  Subject alternative name: " + str);
                    }
                }

                break;
        }
    }
}

If BouncyCastle is the wrong tool and I should use a .NET-integrated class (.NET Core 3.1 or 5.0), please let me know and explain that instead.如果 BouncyCastle 是错误的工具,我应该使用 .NET 集成的 class(.NET Core 3.1 或 5.0),请告诉我并解释一下。 I also need other data like the time a certificate was issued or expires.我还需要其他数据,例如证书颁发或过期的时间。

Here's the workaround I'm using for now.这是我现在使用的解决方法。 It's probably a very dowdy method for a thing as complex as X509.对于像 X509 这样复杂的东西,这可能是一种非常笨拙的方法。 But that's the level I understand from it.但这就是我从中理解的水平。

var match = Regex.Match(certificate.SubjectDN.ToString(), @"(?:^|,)CN=([^,]+)");
if (match.Success)
{
    Console.WriteLine("  Subject: " + match.Groups[1].Value);
}

Unfortunately, there doesn't seem to exist any documentation不幸的是,似乎不存在任何文档

I really doubt in this statement.我真的怀疑这个说法。 .NET has built-in functionality to work with certificates: X509Certificate2 class. .NET 具有使用证书的内置功能: X509Certificate2 class。

And here how the code would look like to get CN (when present. If not present, then most suitable RDN attribute or subject alternative name is returned):以及这里的代码如何获取 CN(如果存在。如果不存在,则返回最合适的 RDN 属性或主题替代名称):

using System.Security.Cryptography.X509Certificates; // ref namespace

//
var cert = new X509Certificate2("cert.pem");
Console.WriteLine("  Subject: " + cert.GetNameInfo(X509NameType.DnsName, false));

For certificate validity or other data, please explore X509Certificate2 properties .有关证书有效性或其他数据,请探索X509Certificate2 属性

I think you were on the right track with your approch on the SubjectDN member.我认为您在SubjectDN成员上的方法是正确的。

Here is a one-liner working example extracting the CN= using Linq (it defaults to empty string if there is no CN=name in the subject):这是一个使用 Linq 提取CN=的单行工作示例(如果主题中没有 CN=name,则默认为空字符串):

certificate.SubjectDN.GetValueList(X509Name.CN).Cast<string>().FirstOrDefault() ?? "";

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM