【问题标题】:How to retrieve the CN name of an X509 certificate with BouncyCastle如何使用 BouncyCastle 检索 X509 证书的 CN 名称
【发布时间】:2021-03-09 17:22:23
【问题描述】:

我有许多域证书的 PEM 文件。我已经了解了如何从文件中读取单个 PEM 对象,并且可以将证书与私钥区分开来。现在我需要知道我找到的每个证书的主题名称。不幸的是,似乎不存在任何文档,而且我无法在网络上找到其他谈论这样做的用户。我发现的大多数代码都是关于 Java 的,并且使用了当前库中不可用的名称(至少对于 C#)。无论从证书中读取 CN 值是否是一项奇特的任务,我都需要这样做。

这是我目前发现的:

安装 NuGet 包 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;
        }
    }
}

如果 BouncyCastle 是错误的工具,我应该使用 .NET 集成类(.NET Core 3.1 或 5.0),请告诉我并解释一下。我还需要其他数据,例如证书的颁发时间或过期时间。

这是我现在使用的解决方法。对于像 X509 这样复杂的东西,这可能是一种非常笨拙的方法。但这就是我从中理解的水平。

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

【问题讨论】:

  • 我认为它就在那里。 Bouncycastle 在x509 目录中拥有处理证书的类,例如x509.X509Certificate。该类有一个属性 SubjectDN,可以检查 CN 和 Subject 名称的其他组成部分。

标签: c# bouncycastle x509


【解决方案1】:

我认为你在SubjectDN 成员上的方法是正确的。

这是一个使用 Linq 和 BouncyCastle 提取 CN= 的单行工作示例(如果主题中没有 CN=name,则默认为空字符串):

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

【讨论】:

    【解决方案2】:

    很遗憾,似乎不存在任何文档

    我真的怀疑这个说法。 .NET 具有使用证书的内置功能:X509Certificate2 类。

    这里的代码将如何获取 CN(如果存在。如果不存在,则返回最合适的 RDN 属性或主题替代名称):

    using System.Security.Cryptography.X509Certificates; // ref namespace
    
    //
    var cert = new X509Certificate2("cert.pem");
    Console.WriteLine("  Subject: " + cert.GetNameInfo(X509NameType.DnsName, false));
    

    关于证书有效期或其他数据,请探索X509Certificate2 properties

    【讨论】:

    • 所以你说 BouncyCastle 是错误的工具,我理解正确吗?你没有提到它,所以我可能假设你不知道 BouncyCastle 是什么。它被另一个处理证书(Certes)的库使用,所以我想我可以在这里重用它。 – 但是您的解决方案无论如何都行不通。该类总是报告它找不到文件,而 BouncyCastle 可以很好地读取它。
    • 我是说 BC 对于这种琐碎的任务来说是不必要的依赖。 As of file not found - 表示指定文件夹中不存在该文件。如果您指定相对路径,它是相对于工作目录的(默认情况下,可执行文件所在的位置)。如果您在使用 X509Certificate2 时遇到问题,请使用您遇到的相关代码和错误更新您的问题。
    • 必须考虑到X509Certificate2 可能是整个 .NET 系统中使用最差的类之一。相比之下,使用 Bouncycastle 是一种乐趣。
    • @JB.WithMonica。我完全不同意你的看法。
    • 意见不如有用的事实有用。
    猜你喜欢
    • 1970-01-01
    • 2014-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多