我一直在嘗試編寫一些代碼來使用Microsoft CryptoAPI。目標很簡單:加密並解密一個字符串。我似乎有它幾乎工作,但最後一次對CryptDecryptMessage的調用失敗。CryptDecryptMessage失敗
所以,我能夠成功地加密我的字符串。然後,當我接收加密的二進制字符串並嘗試解密它時,除了最後一次調用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);
}
好吧,我最初並沒有發現返回的GetLastError值實際上是NTE_BAD_KEY。 CryptDecryptMessage文檔底部的提示暗示了這個錯誤,但是提供了「NTE_BAD_KEY - 80090003 - -2146893821」,如果你沒有注意到-2146893821之前的那個「 - 」,可能會引起混淆,因爲事實上GetLastError返回一個無符號數,其值爲+2148073475,所以我一開始並沒有意識到這是NTE_BAD_KEY。可能這是問題.... – 2013-02-28 17:54:23