与CertAddEncodedCertificateToSystemStore相反,从Windows证书库中获取ASN1证书?

时间:2014-06-18 03:07:06

标签: winapi ssl openssl certificate

我需要以编程方式检索Windows证书存储区中的所有CA证书,以便在OpenSSL中使用。 Win32有一个名为CertAddEncodedCertificateToSystemStore的函数,它与我需要的完全相反:

BOOL WINAPI CertAddEncodedCertificateToSystemStore(
  _In_  LPCSTR szCertStoreName,
  _In_  const BYTE *pbCertEncoded,
  _In_  DWORD cbCertEncoded
);

CertAddEncodedCertificateToSystemStore从X509 ASN1数据缓冲区创建PCCERT_CONTEXT,并将其添加到系统证书存储区。我需要通过系统证书存储区,将PCCERT_CONTEXT转换为X509 ASN1数据缓冲区。

看起来CertSerializeCertificateStoreElement与我想要的非常接近:

BOOL WINAPI CertSerializeCertificateStoreElement(
  _In_     PCCERT_CONTEXT pCertContext,
  _In_     DWORD dwFlags,
  _Out_    BYTE *pbElement,
  _Inout_  DWORD *pcbElement
);

...但显然CertSerializeCertificateStoreElement()返回的数据缓冲区不是正确的DER ASN编码 - 它有额外的东西' - 某种Windows证书存储属性 - 我无法使用它来转换为OpenSSL X509。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

这是我能用于从系统存储转储证书的内容。清理对象不做任何特别的事情。他们只是关闭句柄,释放内存等等。我还抽出了错误检查以保持大小不变​​。

HCERTSTORE hCertStore = CertOpenSystemStore(NULL, _T("ROOT"));
CertStoreCleanup cleanup1(hCertStore);

PCCERT_CONTEXT pCertContext = NULL;
CertContextCleanup cleanup2(pCertContext);

while(pCertContext = CertEnumCertificatesInStore(hCertStore, pCertContext))
{
    CHAR filename[256] = {0};
    INT rc = sprintf_s(filename, sizeof(filename), "cert-%02d.der", i);

    FILE* fp = NULL;
    errno_t et = fopen_s(&fp, filename, "w");
    FileCleanup cleanup3(fp);

    BYTE* pCert = pCertContext->pbCertEncoded;
    DWORD dwSize = pCertContext->cbCertEncoded;

    fwrite(pCert, (size_t)dwSize, 1, fp);
}

不幸的是,Gutmann的dumpasn1或OpenSSL asn1parse都无法处理它们。幽默地,微软自己的证书管理单元无法解析它。有关Microsoft Connect的错误报告:CertEnumCertificatesInStore and friends provide a malformed certifcate

他们看起来很正常,但他们在解析中途中断了。例如,这是微软根证书上的Gutmann的dumpasn1

enter image description here

OpenSSL' asn1parse也有同样的抱怨:

enter image description here


最后,Microsoft在Using Certificates上有一些示例。