如何从 windows 系统 certstore 中的证书中获取 public 密钥

How to get the public key from a certificate in windows system certstore

我已将证书添加到系统商店,如下所示:

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"));

现在我正在创建一个 Cryptographyc Service Provider,需要从此证书中获取 public 密钥以实现 CPExportKey() 函数。

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

此外,如果有人能给我指出 CSP 驱动程序实施的指南或操作方法,那就太好了!我在搜索这些东西的文档时遇到了麻烦。

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

遍历商店中的证书并通过其属性找到我的证书,然后使用 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);
        }
    }
}