CSP如何找到证书的私钥来执行加密操作?

时间:2017-03-19 14:38:02

标签: windows digital-signature private-key cryptoapi

我的问题是:当应用程序调用CSP执行加密操作(例如签名)时,CSP如何分别找到certifcate的私钥?
如果导入证书的证书存储私钥不在本地计算机上(在USB令牌,外部存储器,例如移动设备上),它可以找到?

2 个答案:

答案 0 :(得分:3)

将证书导入系统存储时,Windows会创建一个BLOB结构,其中包含编码证书本身及其属性。 BLOB具有以下结构:

property1_id (4 bytes)
reserved = 0x00000001
property1_length (4 bytes)
property1_data[property1_length]
...
cert_property_id = 0x00000020
reserved = 0x00000001
cert_data_length (4 bytes)
cert_data[cert_data_length]

因此,如果您希望导入的证书具有指向私钥的链接,则需要设置CERT_KEY_PROV_INFO_PROP_ID。您可以使用CRYPT_KEY_PROV_INFO结构和CertSetCertificateContextProperty函数实现此目的。 例如:

    #include <Windows.h>
    #include <wincrypt.h>

void SetKeyLink()
{
HCERTSTORE hStore = NULL;
CRYPT_KEY_PROV_INFO key_prov_info = { 0 };
PCCERT_CONTEXT pCertContext = nullptr;
std::vector<BYTE> der_encoded_cert;

hStore = CertOpenSystemStore(NULL, L"MY");
if (!hStore)
{
    goto Exit;
}

der_encoded_cert = LoadFromFile();

pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING, der_encoded_cert.data(), der_encoded_cert.size());
if (!pCertContext)
{
    goto Exit;
}

    /* For legacy CSP */
key_prov_info.dwProvType = PROV_RSA_AES; // Or YOUR_PROVIDER_TYPE
key_prov_info.dwKeySpec = AT_SIGNATURE; // Or AT_KEYEXCHANGE
key_prov_info.pwszContainerName = L"Your_key_name";
key_prov_info.dwFlags = CERT_SET_KEY_PROV_HANDLE_PROP_ID;
key_prov_info.cProvParam = 0;
key_prov_info.pwszProvName = nullptr;
key_prov_info.rgProvParam = 0;

/*
    Or if you use CNG Key storage provider:

    key_prov_info.pwszProvName = L"Microsoft Software Key Storage Provider"; // Or L"Your_CNG_key_storage_provider_name"
    key_prov_info.pwszContainerName = L"Your_key_name";
    key_prov_info.dwFlags = CERT_SET_KEY_PROV_HANDLE_PROP_ID;
    key_prov_info.dwProvType = 0;
    key_prov_info.dwKeySpec = 0;
    key_prov_info.cProvParam = 0;
    key_prov_info.rgProvParam = 0;
*/

if (!CertSetCertificateContextProperty(pCertContext, CERT_KEY_PROV_INFO_PROP_ID, 0, &key_prov_info))
{
    goto Exit;
}

if (!CertAddCertificateContextToStore(hStore, pCertContext, CERT_STORE_ADD_ALWAYS, NULL))
{
    goto Exit;
}

std::cout << "success";

Exit:

if (pCertContext)
{
    CertFreeCertificateContext(pCertContext);
}

if (hStore)
{
    CertCloseStore(hStore, 0);
}
return;
}

现在你的证书看起来像这样(对不起英文):test_cert

当Windows想要获取私钥时,它会调用CryptAcquireCertificatePrivateKey,然后调用CertGetCertificateContextProperty(...,CERT_KEY_PROV_INFO_PROP_ID,...)。

答案 1 :(得分:0)

我想这取决于CSP使用的密钥库的位置和类型,而不是CSP本身。例如,USB令牌通常需要PKCS#11驱动程序。 CSP&#34;使用&#34;通过司机的关键,但不是&#34;得到&#34;它是因为无法从令牌中提取私钥。但是,软件密钥库可以提供密钥或允许使用它而不暴露内容

例如,Windows密钥库结合了软件和硬件密钥

您告诉CSP使用哪一个,通常使用别名..首先获取所有可用证书,提示用户选择一个,并为CSP提供所选证书的别名以执行加密操作