CSP如何找到证书的私钥进行加密操作?
How CSP find the private key of certificate to perform cryptographic operations?
我的问题是:应用调用CSP进行签名等加密操作时,CSP如何分别找到证书的私钥?
如果导入到cert存储的证书私钥不在本地计算机(USB令牌,外部存储,例如移动设备),它可以找到吗?
当您将证书导入系统存储时,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]
因此,如果您希望导入的证书有link私钥,您需要设置CERT_KEY_PROV_INFO_PROP_ID。您可以使用 CRYPT_KEY_PROV_INFO structure and 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:
// Or L"Your_CNG_key_storage_provider_name"
key_prov_info.pwszProvName = L"Microsoft Software Key Storage Provider";
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;
}
现在你的证书看起来像这样(抱歉不是英语):
当Windows要获取私钥时,调用CryptAcquireCertificatePrivateKey
which in turn calls CertGetCertificateContextProperty(..., CERT_KEY_PROV_INFO_PROP_ID, ...)
。
我的问题是:应用调用CSP进行签名等加密操作时,CSP如何分别找到证书的私钥?
如果导入到cert存储的证书私钥不在本地计算机(USB令牌,外部存储,例如移动设备),它可以找到吗?
当您将证书导入系统存储时,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]
因此,如果您希望导入的证书有link私钥,您需要设置CERT_KEY_PROV_INFO_PROP_ID。您可以使用 CRYPT_KEY_PROV_INFO structure and 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:
// Or L"Your_CNG_key_storage_provider_name"
key_prov_info.pwszProvName = L"Microsoft Software Key Storage Provider";
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;
}
现在你的证书看起来像这样(抱歉不是英语):
当Windows要获取私钥时,调用CryptAcquireCertificatePrivateKey
which in turn calls CertGetCertificateContextProperty(..., CERT_KEY_PROV_INFO_PROP_ID, ...)
。