Я пытался написать код для использования Microsoft CryptoAPI. Цель очень проста: зашифровать и затем расшифровать строку. Кажется, у меня почти все работает, но последний вызов CryptDecryptMessage терпит неудачу.CryptDecryptMessage failing
Итак, я могу успешно зашифровать свою строку. Когда я беру зашифрованную двоичную строку и пытаюсь ее расшифровать, все работает, кроме последнего вызова CryptDecryptMessage. Код дешифрования, который я использую, приведен ниже.
Поскольку код стоит, первый вызов CryptDecryptMessage, чтобы получить требуемый размер выходного буфера, преуспевает, НО он всегда возвращает размер, равный размеру строки открытого текста плюс 6. Затем я увеличиваю свой выходной буфер, и следующий вызов CryptDecryptMessage завершается с ошибкой (возвращаемое значение равно нулю, dwSizeRequired
устанавливается в ноль, ничего не помещается в выходной буфер, а GetLastError
возвращает NTE_BAD_KEY).
С другой стороны, если я раскомментирую линию #define TESTING_INCORRECT
, поведение немного отличается. Первый вызов CryptDecryptMessage успешно завершен. Его возвращаемое значение равно нулю, но GetLastError
возвращает ERROR_MORE_DATA
, чего можно было бы ожидать, и, самое главное, dwSizeRequired
задан с размером оригинальной строки открытого текста, которая была закодирована. Затем я выделяю и вызываю CryptDecryptMessage во второй раз, он снова не работает, как указано выше.
Наконец, у меня есть ключ сертификата в моем хранилище ключей.
Кто-нибудь знает, что здесь не так ????? Благодарю.
void decrypt(std::string& sClearTextString , const std::vector<T_Byte>& sEncryptedBinaryString, const std::string& sKey)
{
BOOL bResult;
HCRYPTPROV hProv;
bResult = CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, 0);
CHECK_CRYPT_ERR(!bResult , "Unable to find crypto context");
HCERTSTORE hStore(NULL);
const char* const pcKey = sKey.empty()? "MY" : sKey.c_str();
hStore = CertOpenSystemStore(0, pcKey);
CHECK_CRYPT_ERR(hStore==NULL, "unable to open certificate store.");
HCERTSTORE CertStoreArray[] = {hStore};
CRYPT_DECRYPT_MESSAGE_PARA DecryptParams;
DWORD DecryptParamsSize = sizeof(DecryptParams);
memset(&DecryptParams, 0, DecryptParamsSize);
DecryptParams.cbSize = DecryptParamsSize;
DecryptParams.dwMsgAndCertEncodingType = (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING);
DecryptParams.cCertStore = sizeof(CertStoreArray)/sizeof(HCERTSTORE);
DecryptParams.rghCertStore = CertStoreArray;
const BYTE* const pbContent = &sEncryptedBinaryString[0];
DWORD dwSize = STATICCAST<DWORD>(sEncryptedBinaryString.size());
DWORD dwSizeRequired = 0;
BYTE* pbOutBuffer = NULL;
//#define TESTING_INCORRECT
#ifdef TESTING_INCORRECT
std::string sDummyBuffer(2,'\0');
pbOutBuffer = (BYTE*)(&sDummyBuffer[0]);
#endif
// Get required buffer size.
bResult = CryptDecryptMessage(&DecryptParams, pbContent, dwSize, pbOutBuffer, &dwSizeRequired, NULL);
CHECK_CRYPT_ERR(!bResult && ERROR_MORE_DATA != GetLastError() , "Unable to get buffer length");
//Allocate buffer
sClearTextString.clear();
sClearTextString.resize(dwSizeRequired+1,0);
pbOutBuffer = (BYTE*)(&sClearTextString[0]);
//Now actually decryt
bResult = CryptDecryptMessage(&DecryptParams, pbContent, dwSize, pbOutBuffer, &dwSizeRequired, NULL);
CHECK_CRYPT_ERR(!bResult , "Unable to decrypt");
CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG);
CryptReleaseContext(hProv, 0);
}
OK, я изначально не понял, что возвращаемое значение GetLastError на самом деле является NTE_BAD_KEY. Примечание в нижней части документации CryptDecryptMessage ссылается на эту ошибку, но дает «NTE_BAD_KEY - 80090003 - -2146893821», что может сбить с толку, если вы не заметите этого маленького «-» перед -2146893821, потому что на самом деле GetLastError возвращает unsigned, значение которого равно +2148073475, поэтому я не понял, что это был NTE_BAD_KEY. Вероятно, это проблема .... –