Второй вызов NCryptOpenKey() для создания данных подписи всегда происходит сбой с NTE_INVALID_PARAMETER (0x80090027).
Я сформулировал проблему в этом примере:
Код: Выделить всё
#define MY_TYPE (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)
HRESULT AcquireCertificatePrivateKey (PCCERT_CONTEXT pSignerCert, NCRYPT_PROV_HANDLE* phProvider, NCRYPT_KEY_HANDLE* phKey, DWORD dwFlags)
{
HRESULT hr;
DWORD dwSize = 0;
CRYPT_KEY_PROV_INFO* pKeyProvInfo = NULL;
NCRYPT_PROV_HANDLE hProvider = NULL;
CheckIf(NULL == pSignerCert || NULL == phKey, E_INVALIDARG);
CheckIfGetLastError(!CertGetCertificateContextProperty(pSignerCert, CERT_KEY_PROV_INFO_PROP_ID, NULL, &dwSize));
pKeyProvInfo = (CRYPT_KEY_PROV_INFO*)malloc(dwSize);
CheckAlloc(pKeyProvInfo);
CheckIfGetLastError(!CertGetCertificateContextProperty(pSignerCert, CERT_KEY_PROV_INFO_PROP_ID, pKeyProvInfo, &dwSize));
Check(NCryptOpenStorageProvider(&hProvider, pKeyProvInfo->pwszProvName, 0));
Check(NCryptOpenKey(
hProvider,
phKey,
pKeyProvInfo->pwszContainerName,
pKeyProvInfo->dwKeySpec,
dwFlags));
if(phProvider)
{
*phProvider = hProvider;
hProvider = NULL;
}
Cleanup:
if(hProvider)
NCryptFreeObject(hProvider);
free(pKeyProvInfo);
return hr;
}
INT main (INT cArgs, __in_ecount(cArgs) PCSTR* ppcszArgs)
{
HRESULT hr;
HCERTSTORE hStoreHandle = NULL;
PCCERT_CONTEXT pSignerCert = NULL;
PCWSTR pcwzSigner = L"name of my certificate";
DWORD dwKeySpec = 0, dwSigLen = 0;
BOOL fCallerFree = FALSE;
NCRYPT_PROV_HANDLE hProvider = NULL;
NCRYPT_KEY_HANDLE hKey = NULL;
BYTE bData[20], *pbSignature = NULL;
hStoreHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_READONLY_FLAG | CERT_STORE_OPEN_EXISTING_FLAG /*CERT_SYSTEM_STORE_CURRENT_USER*/, L"Root");
CheckIfGetLastError(NULL == hStoreHandle);
pSignerCert = CertFindCertificateInStore(hStoreHandle, MY_TYPE, 0, CERT_FIND_SUBJECT_STR, pcwzSigner, pSignerCert);
CheckIfGetLastError(NULL == pSignerCert);
/*
CheckIfGetLastError(!CryptAcquireCertificatePrivateKey(pSignerCert,
CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG, NULL,
(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE*)&hKey,
&dwKeySpec, &fCallerFree));
CheckIf(0 == (dwKeySpec & CERT_NCRYPT_KEY_SPEC), E_FAIL);
CheckIf(!fCallerFree, E_FAIL);
*/
Check(AcquireCertificatePrivateKey(pSignerCert, &hProvider, &hKey, NCRYPT_MACHINE_KEY_FLAG));
fCallerFree = TRUE;
// The real data is a SHA-1 hash, but this should be fine for testing
for(int i = 0; i < sizeof(bData); i++)
bData[i] = i;
Check(NCryptSignHash(hKey, NULL, bData, sizeof(bData), NULL, 0, &dwSigLen, 0));
pbSignature = (BYTE*)malloc(dwSigLen);
CheckAlloc(pbSignature);
Check(NCryptSignHash(hKey, NULL, bData, sizeof(bData), pbSignature, dwSigLen, &dwSigLen, 0));
Cleanup:
if(pbSignature)
free(pbSignature);
if(hKey && fCallerFree)
NCryptFreeObject(hKey);
if(hProvider)
NCryptFreeObject(hProvider);
if(hStoreHandle)
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return hr;
}
Есть идеи?
Спасибо!
Подробнее здесь: https://stackoverflow.com/questions/787 ... 0x80090027