如何使用 CryptUnprotectData 解密字符串

How can I decrypt a string using CryptUnprotectData

提问人:rando314 提问时间:1/26/2023 最后编辑:Simon Mourierrando314 更新时间:1/31/2023 访问量:441

问:

一段时间以来,我一直在尝试通过 c++ CryptUnprotectData 函数解密一些加密数据(AES 密钥加密 chrome cookie),但我似乎无法让它工作。目前,该函数将失败并返回错误代码 13(表示“参数不正确”)。这是我到目前为止的代码:

#include <iostream>
#include <Windows.h>
#include <wincrypt.h>
#include <fstream>
#include <string>
#include <vector>
using namespace std;

std::string GetLastErrorAsString()
{
    DWORD errorMessageID = ::GetLastError();
    if(errorMessageID == 0) {
        return std::string();
    }

    LPSTR messageBuffer = nullptr;

    size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);

    std::string message(messageBuffer, size);

    LocalFree(messageBuffer);

    return message;
}

int main()
{



    string data = "(data I want to decode)";
    cout << data;


    DATA_BLOB DataBytes;

    DataBytes.pbData = (BYTE*)data.data();
    DataBytes.cbData = (DWORD)data.size()+1;


    DATA_BLOB output;
    output.pbData = NULL;
    output.cbData = (DWORD)data.size();


    CryptUnprotectData(&DataBytes, NULL, NULL, NULL, NULL, 0, &output);

    cout << GetLastErrorAsString() << endl;
    cout << output.pbData;


    LocalFree(output.pbData);



    return 0;
}

如果有人能提供任何帮助,将不胜感激。

我已经尝试了存储参数的数据类型的不同变体,尽管它仍然返回此错误。

WinAPI DPAPI

评论

1赞 josh poley 1/26/2023
错误 13 == ,根据文档,这意味着完整性检查失败。您确定 chrome 正在使用 CryptProtectData 吗?基本的谷歌搜索表明他们正在使用 AES 加密。ERROR_INVALID_DATA
0赞 rando314 1/26/2023
对不起,我一定没有说得足够清楚,我的意思是我正在尝试解密用于解密这些 cookie 的 AES 密钥。

答:

-1赞 Torrecto - MSFT 1/26/2023 #1

我修改了您的代码,如下所示。它只实现简单的解密。 并且数据未加密,因此不会返回正确的值。CryptUnprotectData()

#include <stdio.h>
#include <windows.h>
#include <Wincrypt.h>
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
using namespace std;

#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)

#pragma comment (lib, "Crypt32.lib")



int main()
{
    // Decrypt data from DATA_BLOB DataOut to DATA_BLOB DataVerify.

//--------------------------------------------------------------------
// Declare and initialize variables.
    string data = ("data I want to decode \n");
    cout << data;

    LPWSTR pDescrOut = NULL;

    DATA_BLOB DataBytes;
    BYTE* pbDataOutput = (BYTE*)data.data();
    DWORD cbDataOutput = strlen((char*)pbDataOutput) + 1;
    DataBytes.pbData = pbDataOutput;
    DataBytes.cbData = cbDataOutput;
    
    //DATA_BLOB DataVerify;
    


    //--------------------------------------------------------------------
    // The buffer DataOut would be created using the CryptProtectData
    // function. If may have been read in from a file.

    //--------------------------------------------------------------------
    //   Begin unprotect phase.
    BOOL res = CryptUnprotectData(
        &DataBytes,
        &pDescrOut,
        NULL,                 // Optional entropy
        NULL,                 // Reserved
        NULL,                 // Here, the optional 
        // prompt structure is not
        // used.
        0,
        &DataBytes);
    if (res==1)
    {
        printf("The decrypted data is: %s\n", DataBytes.pbData);
        printf("The description of the data was: %s\n", pDescrOut);

    }
    else
    {
        printf("Decryption error!");
    }
//    LocalFree(DataVerify.pbData);
    LocalFree(pDescrOut);
    //LocalFree(DataBytes.pbData);
}

建议在添加其他代码时参考 Microsoft 的官方文档

评论

0赞 rando314 1/27/2023
谢谢你的回答!目前我无法测试它,但我会尽快尝试。
0赞 Torrecto - MSFT 1/27/2023
如果它确实解决了您的问题,请标记我的答案。
0赞 rando314 1/28/2023
对不起,久等了!我知道这不太理想,但我目前没有系统来测试你的答案。我可以在几个小时内测试它。
0赞 rando314 1/28/2023
返回的数据只是未加密的数据,尽管函数 res 等于 0
0赞 Torrecto - MSFT 1/31/2023
@rando314 是的! 如果函数成功,则返回 TRUE(1)。如果函数失败,则返回 FALSE。