如何从Windows系统certstore中的证书获取公钥

时间:2019-03-13 22:07:07

标签: c++ windows cryptoapi certificate-store

我已将证书添加到系统存储中,如下所示:

PCCERT_CONTEXT pCertContext;
HCERTSTORE hCertStore;
CRYPT_KEY_PROV_INFO provInfo;

if (pCertContext = CertCreateCertificateContext(MY_ENCODING_TYPE, certDER, certSize)) {
    provInfo.pwszContainerName = idCert;
    provInfo.pwszProvName = provName;
    provInfo.dwProvType = provType;
    provInfo.dwFlags = 0;
    provInfo.cProvParam = 0;
    provInfo.rgProvParam = NULL;
    provInfo.dwKeySpec = AT_SIGNATURE;

    if (!CertSetCertificateContextProperty(pCertContext, CERT_KEY_PROV_INFO_PROP_ID, 0, &provInfo)) Error(TEXT("CertSetCertificateContextProperty"));

    if (!(hCertStore = CertOpenSystemStore(NULL, L"MY"))) Error(TEXT("CertOpenSystemStore"));
    if (!CertAddCertificateContextToStore(hCertStore, pCertContext, CERT_STORE_ADD_REPLACE_EXISTING, NULL)) Error(TEXT("CertAddCertificateContextToStore"));
    CertFreeCertificateContext(pCertContext);
} else Error(TEXT("CertCreateCertificateContext"));

现在,我正在创建一个密码学服务提供者,需要从此证书中获取公钥以实现CPExportKey()函数。

这可能吗?如果是,该怎么办?

此外,如果有人可以向我介绍CSP驱动程序实施的一种指南或方法,那就太好了!我在寻找这些东西的文档时遇到了麻烦。

1 个答案:

答案 0 :(得分:2)

所以我找到了下面的解决方案。省略了所有不必要的代码。

遍历商店中的证书及其属性,以查找我的证书,然后使用CryptDecodeObjectEx()函数将密钥转换为RSA_CSP_PUBLICKEYBLOB格式。

密钥保存在pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData的此位置,其大小保留在pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData

HCERTSTORE hCertStore = NULL;
PCCERT_CONTEXT pCertContext = NULL;
PBYTE pbPKEY = NULL;
DWORD iPKEYSize;

hCertStore = CertOpenSystemStore(NULL, L"MY");

while(pCertContext = CertEnumCertificatesInStore(
    hCertStore,
    pCertContext))
{
    DWORD dwPropId = 0;
    while(dwPropId = CertEnumCertificateContextProperties(
        pCertContext, // The context whose properties are to be listed.
        dwPropId))    // Number of the last property found.  
    {
        // ...
        // here I compare the properties to see if it is the certificate that I want.
        // ...
        CryptDecodeObjectEx((PKCS_7_ASN_ENCODING | X509_ASN_ENCODING), 
            RSA_CSP_PUBLICKEYBLOB, 
            pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData, 
            pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData, 
            CRYPT_ENCODE_ALLOC_FLAG, 
            NULL, 
            &pbPKEY, 
            &iPKEYSize);

            // pbData and pcbDataLen are output parameters of the function
            *pcbDataLen = iPKEYSize;
            memcpy(pbData, pbPKEY, *pcbDataLen);
            LocalFree((HANDLE)pbPKEY);
        }
    }
}