How to check if a X509 certificate has “Extended Validation” switched on?

后端 未结 2 521
时光说笑
时光说笑 2020-12-28 08:29

I\'m struggling to find a reliable way to check from my C# (.Net 4.0) application if an X509Certificate (or X509Certificate2) has the \"Extended Validation\" (EV) flag set.

2条回答
  •  时光说笑
    2020-12-28 09:00

    You could check if the X509Certificate contains one of these OIds. Additionally you can check Chromium's Source for a list of implemented OIds. You can find the Source here. If you'd like to stick to Firefox, you can grab the implementation here.

    I now updated my source and tested it. I've written a small method to validate a X509Certificate2 against the OId-List from Wikipedia/Chromium. In this method I am using the Wikipedia-List, it might be better to take the Chromium-List instead.


    How is the OId saved?

    Each CAhas one or more ObjectIds OIds. They are not saved as an Extension as you might guess, they are saved as an entry within the Policy Extensions. To get the exact Extension it's recommended to use the Oid of the Policy Extension itself rather then using a Friendly Name. The OId of the Policy Extensions is 2.5.29.32.

    Extracting the Information

    To get the inner content of the Policy Extensions we can use System.Security.Cryptography.AsnEncodedData to convert it to a readable string. The string itself contains the policies we need to match against our string[] to ensure if it contains one of the OIds of an EV Certificate.

    Source

        /// 
        /// Checks if a X509Certificate2 contains Oids for EV
        /// 
        /// 
        /// 
        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()
                );
        }
    

    If you need some source to get started:

        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;
        }
    

    If someone knows a better way to achieve this goal, please let us know.

提交回复
热议问题