如何设置证书用途?

时间:2018-12-20 11:40:00

标签: c# x509certificate2

有一个GlobalSignCA。在大多数情况下,其根证书已存在于Windows证书存储中。 但是有时(尤其是在旧的Windows版本上),存储中不包含证书。

我需要检查证书是否存在,如果不存在则将其导入。我将证书导出到文件中,并使用以下代码将其导入:

joda.time

代码添加了证书,但检查了所有证书用途:

Result

我不想为证书添加额外的用途,只想设置具有其他根CA的证书,如下所示:

Expect

如何以编程方式进行?

1 个答案:

答案 0 :(得分:0)

您需要使用CertSetCertificateContextProperty函数来设置存储附加属性。

dwPropId参数中,您传递CERT_ENHKEY_USAGE_PROP_ID。您可以在Wincrypt.h C ++头文件中找到其数值。在给定的情况下,dwPropId为9:

#define CERT_ENHKEY_USAGE_PROP_ID           9

dwFlags中,您传递零(0)。

pvData参数(在托管签名中为IntPtr)中,您将非托管指针传递到ASN.1编码的字节数组,该数组表示对象标识符的集合,其中每个OID表示显式启用密钥用法。

这是互操作签名:

[DllImport("Crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern Boolean CertSetCertificateContextProperty(
    [In] IntPtr pCertContext,
    [In] UInt32 dwPropId,
    [In] UInt32 dwFlags,
    [In] IntPtr pvData,
);

添加对System.Runtime.InteropServices命名空间的使用引用。

接下来,准备一系列关键用法:

  1. 创建OidCollection类的新实例。
  2. 将必需的OID添加到集合中。
  3. 使用创建的OID集合实例化X509EnhancedKeyUsageExtension类。此ctor重载很好:X509EnhancedKeyUsageExtension(OidCollection, Boolean)
  4. EKU扩展的
  5. RawData属性将包含ASN.1编码的字节数组,该数组将传递给CertSetCertificateContextProperty函数。

CertSetCertificateContextProperty函数的最后一个参数为IntPtr类型,并且期望有指向非托管内存块的指针,因此:

  1. 使用Marshal.AllocHGlobal(eku.RawData.Length)在非托管内存中分配适当大小的缓冲区。
  2. 使用Marshal.Copy(byte[], IntPtr, int, int)静态方法重载将eku.RawData字节数组复制到步骤1中获取的非托管指针。
  3. 调用CertSetCertificateContextProperty函数。如果返回true,那么一切正常。

完成所有作业后,必须释放非托管资源以避免内存泄漏。使用Marshal.FreeHGlobal(IntPtr)方法释放在Marshal.AllocHGlobal调用期间获取的指针。