如何从客户端证书中读取公用名?

时间:2014-09-04 23:34:15

标签: c# .net client-certificates

我们的应用程序需要一个数据,它包含在客户端证书的通用名称中。目前,我正试图从HttpContext.Current.Request.ClientCertificate获取它。我怎么读出来的?可悲的是,我正在尝试对这个盲人进行编码,同时我弄清楚为什么SoapUI没有发送证书,所以除了阅读有关MSDN上的对象并探索空属性之外,我没有尝试过多,但我不确定我正在寻找什么。那么回顾一下,我需要做些什么来从这个证书中提取通用名称? TIA

5 个答案:

答案 0 :(得分:7)

我可能为时已晚,无法回答您的问题,但我希望这有助于其他寻求从证书中获取通用名称的方式。

如果使用“主题”,则可能需要删除其他不必要的信息。 例如,CN = localhost,OU = DepartmentName,O = CompanyName,L = Location,S = State,C = Country

Dim store As New X509Store(StoreName.My, StoreLocation.LocalMachine)
store.Open(OpenFlags.ReadOnly)
store.Certificates(0).Subject

但是如果您使用下面的代码,您将获得'localhost',它直接为您提供证书的通用名称。

Dim store As New X509Store(StoreName.My, StoreLocation.LocalMachine)
store.Open(OpenFlags.ReadOnly)
store.Certificates(0).GetNameInfo(X509NameType.SimpleName, False)

以下是供参考的链接: - https://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2.getnameinfo(v=vs.110).aspx

答案 1 :(得分:5)

我对证书知之甚少。这是我的工作流程:

我开始于:

HttpRequest.ClientCertificate

导致我:

HttpClientCertificate(作为返回类型)。

它似乎有一些属性,但没有明确命名为通用名称

Google搜索:HttpClientCertificate通用名称:

Problem with extracting X509 certificate from Context on web service side

其中有一些代码:

//extracting Common name from certificate
Subject = cert.Subject.ToString();

然后去了:

HttpClientCertificate.Subject

备注:

  

如果指定的String没有子字段,则HttpClientCertificate集合返回以逗号分隔的子字段列表。例如,C = US,O = Msft。

由于我的知识极其有限,我知道 Common Name = 在此列表中。目前我没有实际的方法来测试这个,但是要解析你想要的名称这个值应该不难。

这是一个很好的问题(+1),我很高兴你问它,因为它可能对未来的读者有用。

我创建了一个DotNetFiddle Example,即使它使用HttpWebRequest来获取X509Certificate类,它也有一个Subject属性,它在www.google.com上为https返回了以下值:

  

CN = www.google.com,O = Google Inc,L = Mountain View,S = California,C = US

所以我倾向于相信HttpClientCertificate上的Subject将是相同的值(知道CN意味着CommonName)。

答案 2 :(得分:1)

由于证书格式的差异,您可能需要进行调整。

以下是一些代码:

HttpClientCertificate theHttpCertificate = HttpContext.Current.Request.ClientCertificate; 
// split the subject into its parts
string[] subjectArray = theHttpCertificate.Subject.Split(',');
string[] nameParts;
string CN = string.Empty;
string firstName = string.Empty;
string lastName = string.Empty;

foreach (string item in subjectArray)
{
    string[] oneItem = item.Split('=');
    // Split the Subject CN information
    if (oneItem[0].Trim() == "CN")
    {
       CN = oneItem[1];
       if (CN.IndexOf(".") > 0)
       {// Split the name information
           nameParts = CN.Split('.');
           lastName = nameParts[0];
           firstName = nameParts[1];
        }
    }
}

答案 3 :(得分:1)

只是Linq的一个oneliner。

var kvs = cert.Subject.Split(',').Select(x => new KeyValuePair<string, string>(x.Split('=')[0], x.Split('=')[1])).ToList();

返回通用列表。不要在这里使用字典,因为Subject可以包含重复的字段。

答案 4 :(得分:0)

最好的做法是使用使用名称类型和布尔标志的内置 GetNameInfo 方法

假设您使用此扩展方法:

[return:MaybeNull]
public static X509Certificate2? GetCodeSignCertificate(this Assembly asm)
{
    if (asm is null)
    {
        throw new ArgumentNullException(nameof(asm));
    }

    if (!File.Exists(asm.Location))
    {
        return null;
    }

    using var cert=System.Security.Cryptography.X509Certificates.X509Certificate.CreateFromSignedFile(asm.Location);
    if (cert is null)
        return null;

    return new X509Certificate2(cert);
}

然后您可以使用类中的类型来获取证书,如下所示:

[TestMethod()]
public void TryGetCodeSigning()
{
    //var item = new Walter.CallStack();

    var item = new List<string>();
            
    using var cert = item.GetType().Assembly.GetCodeSignCertificate();
    Assert.IsNotNull(cert.GetNameInfo(X509NameType.SimpleName,true));

}

获取证书签名机构的名称

cert.GetNameInfo(X509NameType.SimpleName,true)

获取证书签署人的姓名

cert.GetNameInfo(X509NameType.SimpleName,false)

看看 X509NameType 是否适合您。