0

我一直在尝试编写一些代码来使用 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);
}
4

1 回答 1

2

我会调查正在使用的密钥。2148073475的返回码实际上转化为0x80090003,也就是NTE_BAD_KEY。234 的 GetLastError 是 ERR_MORE_DATA,表示缓冲区大小不足。

认为问题在于期望对 CryptDecryptMessage 的第一次调用将接收 NULL 作为指向 pbDecrypted 的指针,因为它是一个大小调用,但由于它的非 null 删除了注释,它给出了 234 结果,认为它试图解密某些东西已经确定尺寸。

如果大小(第一次)调用上的接收缓冲区应该为空的假设是正确的,那么这导致我建议密钥可能在某种程度上根据 NTE_BAD_KEY 错误代码受到怀疑。

希望能激起一些对你有帮助的想法。

于 2013-02-28T18:22:36.280 回答