1

由于 Thawte(和其他几个 CA)从 1024 位根转换为新的、更安全的 2048 位根,因此某些 SSL 证书(例如 Thawte 通配符证书)的验证变得复杂,因为它包含“thawte 主根 CA “在其证书链中。

这导致某些浏览器在 Windows 中安装时无法验证证书。可在http://www.tbs-certificats.com/FAQ/en/608.html找到手动解决方案。

这里的挑战在于,对于某些托管环境,例如 Microsoft Azure,网站的底层操作系统实例可以随时更改,这种手动更改将毫无用处,因为根证书将不断“刷新”到其原始“错误”状态。

一些文章为我指出了正确的方向,以编程方式进行此更改( http://en-us.sysadmins.lv/Lists/Posts/Post.aspx?List=332991f0-bfed-4143-9eea-f521167d287c&ID=69http ://forums.asp.net/t/1531893.aspx/1 )。似乎唯一的方法是使用 CryptoAPI。

以下是我尝试实现此目的的控制台应用程序代码:

class Program
    {
        [DllImport("Crypt32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool CertGetCertificateContextProperty(
            IntPtr pCertContext,
            uint dwPropId,
            Byte[] pvData,
            ref uint pcbData
        );

        [DllImport("Crypt32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool CertSetEnhancedKeyUsage(
            IntPtr pCertContext,
            IntPtr pUsage
        );

        static void Main(string[] args)
        {
            try
            {
                X509Store store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
                store.Open(OpenFlags.ReadWrite | OpenFlags.OpenExistingOnly);

                X509Certificate2 cert = store.Certificates.Find(X509FindType.FindBySerialNumber, "344ed55720d5edec49f42fce37db2b6d", false)[0];

                if (!cert.Equals(IntPtr.Zero))
                {
                    uint pcbData = 0;
                    // if the function returns True, then certificate purposes are either disabled or constrained
                    // otherwise (False) valid purposes are determined by certificate's EKU
                    if (CertGetCertificateContextProperty(cert.Handle, 0x9, null, ref pcbData))
                    {
                        // create a buffer for ASN.1 encoded byte array
                        byte[] pvData = new byte[pcbData];
                        // call the function again to write actual data
                        CertGetCertificateContextProperty(cert.Handle, 0x9, pvData, ref pcbData);
                        // instantiate AsnEncodedData object with ASN.1 encoded byte array
                        AsnEncodedData asn = new AsnEncodedData("", pvData);
                        // instaintiate X509EnhancedKeyUsageExtension to retrieve OIDs in a readable form
                        X509EnhancedKeyUsageExtension eku = new X509EnhancedKeyUsageExtension(asn, false);
                        // if none OIDs are defined, then all certificate purposes are explicitly diabled in the properties
                        if (eku.EnhancedKeyUsages.Count == 0)
                        {
                            Console.WriteLine("All purposes for this certificate are explicitly disabled.");
                        }
                        else
                        {
                            // constrained OIDs
                            OidCollection keyUsages = eku.EnhancedKeyUsages;

                            // disable all purposes by emptying EnhancedKeyUsages
                            IntPtr pUsage = Marshal.AllocHGlobal(0);
                            CertSetEnhancedKeyUsage(cert.Handle, pUsage);                           
                        }
                    }
                    else
                    {
                        Console.WriteLine("Valid purposes are determined by the certificate EKU extension.");
                    }
                }
                else
                {
                    throw new ArgumentException("An attempt was made to access an uninitialized object.");
                }

                store.Close();
            }
            catch (CryptographicException)
            {
                Console.WriteLine("Information could not be written out for this certificate.");
            }

            Console.ReadLine();
        }
    }

这样做的结果似乎是积极的,因为在控制台应用程序的第二次运行中,所有目的似乎都已禁用,但需要注意的是,更改在 certmgr.msc 中不可见,目的看起来仍处于启用状态。

此外,当上面的代码放在我的 MVC 网站的 Global.asax 中时,它似乎对证书没有任何影响。

所以我的问题是2倍:

  1. 如何禁用证书的所有用途,从而导致 Windows 证书管理单元显示证书更改?

  2. 如何在 ASP.NET 中持续实现这一目标?

4

0 回答 0