4

我已经向系统存储添加了一个证书,如下所示:

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 服务提供者,需要从该证书中获取公钥来实现 CPExportKey() 函数。

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

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

4

1 回答 1

4

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

遍历存储中的证书及其属性以找到我的证书,然后使用该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);
        }
    }
}
于 2019-03-15T20:43:38.407 回答