如何验证证书主题的规范名称(通用名称,cn)?

时间:2014-10-19 22:53:16

标签: c# validation ssl x509certificate

在C#中,我创建了一个与服务器的SSL连接,如下所示:

var hostname = "www.example.com";
var client = new TcpClient(hostname, 443);
var sslStream = new SslStream(client.GetStream());
sslStream.AuthenticateAsClient(hostname);

完成上述操作而不抛出异常后,我知道服务器证书已经过验证,主机名与主题相匹配。该主题可通过属性sslStream.RemoteCertificate.Subject访问,该属性是DN格式的字符串,类似于

CN=www.example.com, O=Example Inc, L=New York, S=New York, C=US

CN=*.example.com, OU=Certificate Authority Validated

出于深奥的原因,我想针对同一个证书主题验证另一个字符串(另一个主机名)。如何正确验证特定主机名是否与证书主题相匹配?

2 个答案:

答案 0 :(得分:3)

以下是相关标准:RFC2818 Section 3.1

特别重要:问题是如何解析主题字符串,正确答案是:一般情况下,你不应该这样做。解析Subject字符串已经被弃用,因为至少2000年编写RFC2818时,有利于subjectAltName.dNSName。

以下是单声道实现:(在以下文件中搜索checkServerIdentityhttps://github.com/mono/mono/blob/master/mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificate.cs

我之前将此信息作为问题的修改发布,并表示它不算作答案,因为代码不完整 - 标记为TODODEPRECATED的代码段。但是现在我已经更仔细地审查了代码和RFC,并发现RFC标准需要DEPRECATED注释,TODO注释实际上已经完成 - 显然有人忘了删除TODO评论。

答案 1 :(得分:1)

如果要模拟SSL主题名称验证,则必须执行一些操作,因为此过程不是很简单。以下是在证书中实施主题名称验证的指南:

  1. 评估X509Certificate2对象的主题备用名称扩展名。如果此扩展名不存在,则:
  2. 1.1。使用以下正则表达式模式从证书中提取CN属性:'CN=([^,]+)'并使用所需名称对其进行验证。由于CN属性可能包含通配符,因此您应该使用正则表达式对其进行验证。以下是简单通配符类的示例。

    class Wildcard : Regex {
        public Wildcard(String pattern) : base(WildcardToRegex(pattern)) { }
        public Wildcard(String pattern, RegexOptions options) : base(WildcardToRegex(pattern), options) { }
        public static String WildcardToRegex(String pattern) {
            return "^" + Escape(pattern).Replace("\\*", ".*") + "$";
        }
    }
    
    1. 如果出现SAN扩展,请忽略主题字段验证,并以相同方式对DNSName和IPAddress替代名称的集合使用地址验证。

    2. 如果步骤1或2成功,请检查名称约束扩展名结束验证的完整证书链(最多为根证书):

      3.1。如果Name Constraints定义Exclude部分,请验证另一个名称是否与列表中的任何条目不匹配。否则,此证书不允许使用该名称(不执行步骤3.2)。

      3.2。如果Name Constraints定义Include部分,请验证另一个名称是否与此部分中的任何条目匹配。如果其他名称不属于“包含”部分中的任何条目,则此证书不允许使用此名称。

    3. 不幸的是,.NET没有一个可以代表SAN扩展的本机类,因此您必须编写自己的解码器或使用我自己的.NET扩展库(PKI.Core.dll)来自{{ 3}}

      以下类代表SAN扩展:PowerShell PKI project