2013-02-28 7 views
0

Я пытался написать код для использования 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); 
} 
+0

OK, я изначально не понял, что возвращаемое значение GetLastError на самом деле является NTE_BAD_KEY. Примечание в нижней части документации CryptDecryptMessage ссылается на эту ошибку, но дает «NTE_BAD_KEY - 80090003 - -2146893821», что может сбить с толку, если вы не заметите этого маленького «-» перед -2146893821, потому что на самом деле GetLastError возвращает unsigned, значение которого равно +2148073475, поэтому я не понял, что это был NTE_BAD_KEY. Вероятно, это проблема .... –

ответ

2

Я бы изучил используемые ключи. Код возврата 2148073475 фактически переводится в 0x80090003, то есть NTE_BAD_KEY. GetLastError из 234 - ERR_MORE_DATA, что указывает на недоразмерный буфер.

Я думаю проблема заключается в ожидании того, что первый вызов CryptDecryptMessage получит NULL в качестве указателя на pbDecrypted, поскольку его проклейка вызова, а как его ненулевой с комментарием удаляется, он дает 234 результата думая, что пытается дешифровать то, что уже было размером.

Если презумпция того, что буфер приема на запросе на калибровку (первый) является нулевым, является правильным, то это заставляет меня предположить, что ключ (ы) может быть подозрительным каким-либо образом в коде ошибки NTE_BAD_KEY.

Надеюсь, что вас заинтересует какая-то полезная мысль.

+0

Да, это, по сути, содержание моего комментария выше, но вы ответ чуть менее загадочный, чем мой комментарий, и он предоставил немного больше информации для других. Благодарю. –

+0

Нет проблем - извините, я не заметил вашей заметки, когда отправил ответ! –