我一直在尝试编写一些代码来使用 Microsoft CryptoAPI。目标很简单:加密然后解密一个字符串。我似乎几乎可以正常工作,但是对 CryptDecryptMessage 的最后一次调用失败了。
因此,我能够成功加密我的字符串。然后,当我获取加密的二进制字符串并尝试对其进行解密时,除了最后一次调用 CryptDecryptMessage 之外,一切正常。我正在使用的解密代码如下。
就代码而言,第一次调用 CryptDecryptMessage 以获取所需的输出缓冲区大小成功,但它总是返回等于明文字符串大小加 6 的大小。然后我调整输出缓冲区的大小,下一次调用到 CryptDecryptMessage 失败(返回值为零,dwSizeRequired
设置为零,输出缓冲区中没有任何内容,并GetLastError
返回 NTE_BAD_KEY)。
另一方面,如果我取消注释该#define TESTING_INCORRECT
行,行为会略有不同。对 CryptDecryptMessage 的第一次调用成功。它的返回值为 0,但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);
}