2017-03-19 114 views
1

我的問題是:當一個應用程序調用CSP執行加密操作時,如簽名,CSP如何分別找到證書的私鑰?
如果一個證書導入到證書存儲區的私鑰不在本地計算機上(在USB令牌上,外部存儲器上,例如移動設備上),它能找到嗎?
CSP如何找到證書的私鑰來執行加密操作?

+0

我會說這取決於使用的CSP。如果證書由USB令牌的CSP管理,則它期望私鑰存在於USB令牌中。 – Robert

+0

CSP發現並訪問密碼操作的私鑰的機制是什麼?你能給我更多的細節嗎? –

+0

我想這取決於CSP使用的密鑰庫的位置和類型,而不是CSP本身。例如,USB令牌通常需要PKCS#11驅動程序。 CSP通過驅動程序「使用」密鑰,但不會「獲取」密鑰,因爲無法從令牌中提取私鑰。然而,軟件密鑰庫可以提供密鑰或允許在不暴露內容的情況下使用密鑰(如Windows密鑰庫)。這是您要求的嗎? – pedrofb

回答

0

我想這取決於CSP使用的密鑰庫的位置和類型,而不是CSP本身。例如,USB令牌通常需要PKCS#11驅動程序。 CSP通過驅動程序「使用」密鑰,但不會「獲取」密鑰,因爲無法從令牌中提取私鑰。然而軟件密鑰庫可以提供密鑰或允許使用它沒有使內容

例如視窗密鑰庫結合軟件和硬件鍵

你告訴CSP使用哪一種,通常有一個別名。首先你獲取所有可用證書,提示用戶選擇一個證書,並向CSP提供選定證書的別名以執行加密操作

1

將證書導入到系統存儲時,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,...)。

+0

謝謝。優秀的解釋。 –

相關問題