如何检查是否X509证书“扩展验证”开启?(How to check if a X509 certi

2019-07-19 06:53发布

我在努力寻找一种可靠的方式,从我的C#检查(.NET 4.0)应用程序,如果一个X509Certificate(或X509Certificate2)具有“扩展验证”(EV)标志设置。 有谁知道最好的方法是什么?

Answer 1:

你可以检查X509Certificate包含这些之一OID秒。 此外,您可以检查Chromium的源动力实现OID列表。 你可以找到源头在这里 。 如果你想坚持到Firefox,你可以抓住的实施在这里 。

现在我更新了我的源和测试它。 我写了一个小方法来验证X509Certificate2对维基百科/铬的OID名录。 在这种方法中,我使用维基百科的名录,它可能会更好走铬列表,而不是。


该OID是如何保存的?

每个CA都有一个或多个的ObjectID OId秒。 他们不是保存为扩展您可能已经猜到,它们被保存为策略扩展中的条目。 为了得到它的推荐使用的OID确切扩展Policy Extension本身而不是使用一个好记的名称。 该政策扩展的OID是2.5.29.32

提取信息

要获得策略扩展的内部内容,我们可以使用System.Security.Cryptography.AsnEncodedData将其转换为可读string 。 该字符串包含我们需要来匹配我们的政策string[]以确保是否包含的OID的一个EV Certificate

资源

    /// <summary>
    /// Checks if a X509Certificate2 contains Oids for EV
    /// </summary>
    /// <param name="certificate"></param>
    /// <returns></returns>
    private static bool IsCertificateEV(X509Certificate2 certificate)
    {
        // List of valid EV Oids
        // You can find correct values here:
        // http://code.google.com/searchframe#OAMlx_jo-ck/src/net/base/ev_root_ca_metadata.cc&exact_package=chromium
        // or in Wikipedia
        string[] extendedValidationOids = 
        {
            "1.3.6.1.4.1.34697.2.1",
            "1.3.6.1.4.1.34697.2.2",
            "1.3.6.1.4.1.34697.2.1", 
            "1.3.6.1.4.1.34697.2.3", 
            "1.3.6.1.4.1.34697.2.4",
            "1.2.40.0.17.1.22",
            "2.16.578.1.26.1.3.3",
            "1.3.6.1.4.1.17326.10.14.2.1.2", 
            "1.3.6.1.4.1.17326.10.8.12.1.2",
            "1.3.6.1.4.1.6449.1.2.1.5.1",
            "2.16.840.1.114412.2.1",
            "2.16.528.1.1001.1.1.1.12.6.1.1.1",
            "2.16.840.1.114028.10.1.2",
            "1.3.6.1.4.1.14370.1.6",
            "1.3.6.1.4.1.4146.1.1",
            "2.16.840.1.114413.1.7.23.3",
            "1.3.6.1.4.1.14777.6.1.1", 
            "1.3.6.1.4.1.14777.6.1.2",
            "1.3.6.1.4.1.22234.2.5.2.3.1",
            "1.3.6.1.4.1.782.1.2.1.8.1",
            "1.3.6.1.4.1.8024.0.2.100.1.2",
            "1.2.392.200091.100.721.1",
            "2.16.840.1.114414.1.7.23.3",
            "1.3.6.1.4.1.23223.2", 
            "1.3.6.1.4.1.23223.1.1.1", 
            "1.3.6.1.5.5.7.1.1",
            "2.16.756.1.89.1.2.1.1",
            "2.16.840.1.113733.1.7.48.1",
            "2.16.840.1.114404.1.1.2.4.1",
            "2.16.840.1.113733.1.7.23.6",
            "1.3.6.1.4.1.6334.1.100.1",
        };

        // Logic:
        // Locate Certificate Policy Extension
        // Convert to AsnEncodedData (String)
        // Check if any of the EV Oids exist
        return (
                from X509Extension ext in certificate.Extensions 
                where ext.Oid.Value == "2.5.29.32" 
                select new AsnEncodedData(ext.Oid, ext.RawData).Format(true))
                .Any(asnConvertedData => extendedValidationOids.Where(asnConvertedData.Contains).Any()
            );
    }

如果你需要一些源开始:

    static void Main(string[] args)
    {
        // Create Delegate for analysis of X509Certificate
        ServicePointManager.ServerCertificateValidationCallback = ValidateServerCertificate;

        // Make sample request to EV-Website to get Certificate
        var wc = new WebClient();
        wc.DownloadString("https://startssl.com");  // EV
        wc.DownloadString("https://petrasch.biz");  // Not EV
        Console.ReadLine();
    }

    public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
        var cert = (X509Certificate2) certificate;
        Console.WriteLine("Certificate: " + cert.GetNameInfo(X509NameType.SimpleName, true) + " -> " + IsCertificateEV(cert));
        return true;
    }

如果有人知道一个更好的方式来实现这一目标,请告诉我们。



Answer 2:

我想我会后,即使这个问题是很老了更完整的答案。 所以,这是一个完整的,我不会捎带关闭现有的答案。

EV证书有需要为了通过一个浏览器认为该证书是EV几张支票。

  1. 该证书是已知的EV政策策略标识符。
  2. 该证书的根的指纹相匹配的固定策略标识符。
  3. 证书必须通过网上撤销检查。
  4. 如果证书的notBefore(颁发日期)是1/1/2015后,该证书必须支持证书透明度。
  5. 该证书必须由受信任的根颁发。
  6. 如果有多个信任路径所有连锁是有效的。

让我们仔细分析每一种。

策略标识符

证书有一个叫做策略标识符的扩展。 扩展可以从访问X509Certificate2.Extensions财产。 该政策标识符扩展具有的对象标识符(“OID”) 2.5.29.32 。 因此,我们可以用这样的获取原始扩展:

var extension = certificate.Extensions["2.5.29.32"]

如果返回NULL,意思是有没有政策,就可以马上蝙蝠认为这不是一个EV证书。

更可能的是该证书具有某种政策。 在这种情况下,需要对数据进行解码。 该属性将它送给您可以在原始ASN.1,我们需要弄明白它。

不幸的是,没有在.NET中,今天能做到开箱即用。 然而CryptDecodeObjectEx如果您使用平台调用可以做到这一点。 做好细节,所以我就离开了,但有大量的信息四处展示如何调用该函数。 你会想设置的值lpszStructType参数来调用它(IntPtr)16 。 这会给你回一个CERT_POLICIES_INFO结构,具有计数和指针数组CERT_POLICY_INFO结构。 这种结构有一个字段上叫pszPolicyIdentifier 。 正是这种政策OID,我们感兴趣的内容。

每个证书颁发机构都有他们使用,使证书为EV一个或多个OID。 每个CA记录了他们自己的政策页。 然而,要达到这样的一个先进的最新列表最好的地方可能是Chromium的源代码 。

如果证书有一个相匹配的OID的一个政策,那么我们可以继续进行下一步检查。

根指纹

如果你在上面的链接看看铬源,你会看到除了策略标识符,它也保持了根SHA256指纹。

这是因为,除了具有合适OID的证书,它必须由一个CA,其匹配指纹发行。 在铬源,我们看到的是这样的:

{{0x06, 0x3e, 0x4a, 0xfa, 0xc4, 0x91, 0xdf, 0xd3, 0x32, 0xf3, 0x08,
      0x9b, 0x85, 0x42, 0xe9, 0x46, 0x17, 0xd8, 0x93, 0xd7, 0xfe, 0x94,
      0x4e, 0x10, 0xa7, 0x93, 0x7e, 0xe2, 0x9d, 0x96, 0x93, 0xc0}},
    {
        // AC Camerfirma uses the last two arcs to track how the private key
        // is managed - the effective verification policy is the same.
        "1.3.6.1.4.1.17326.10.14.2.1.2", "1.3.6.1.4.1.17326.10.14.2.2.2",
    }

因此,该证书必须具有的“1.3.6.1.4.1.17326.10.14.2.1.2”或“1.3.6.1.4.1.17326.10.14.2.2.2”策略标识符,但根本必须有上面看到二进制的SHA1指纹。

这可以防止流氓CA从以往任何时候都使用它自己并不拥有的策略ID。

吊销检查

如果浏览器无法检查证书已被吊销,那么就不会被认为是EV证书。 在线吊销检查一定要做,但客户端可以缓存的结果。

您可以执行撤销使用时检查X509Chain.Build通过调用之前设置上链相应的标志Build

证书透明度

这一个是有点难以检查,但谷歌有适当的文件证明透明度网站 。 如果证书1/1/2015之后发出,需要证书的透明度。 某些证书也被列入白名单的Chrome上所指示的Chromium项目页面 。

受信任的根

这一个是相当简单的,但证书必须属于受信任的根。 如果证书自签名,它不可能是电动汽车。 打电话时,这可以再次检查X509Chain.Build()

多信任路径

这是可能的证书有多个信任路径,说,如果该证书是由根,这是跨签署颁布。 如果有多个信任路径,所有路径必须是有效的。 同样吊销检查必须在所有路径来完成。 如果任何路径的显示证书被撤销,则证书无效。

不幸的是.NET,甚至Win32的没有检查所有证书链,甚至出现多个链的一大手段,据我所知。

所有这些组合,如果他们都通过,则该证书可以被认为是EV证书。



文章来源: How to check if a X509 certificate has “Extended Validation” switched on?