由于 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=69和http ://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倍:
如何禁用证书的所有用途,从而导致 Windows 证书管理单元显示证书更改?
如何在 ASP.NET 中持续实现这一目标?