在虚幻引擎中使用DPAPI对用户输入进行加密和解密,但解密与原始输入不匹配

Using DPAPI in unreal to encrypt and decrypt user input, but the decryption doesn't match the original input

提问人:MashedPotato6587 提问时间:3/16/2023 更新时间:3/16/2023 访问量:62

问:

我正在提示用户输入(在本例中为安全令牌)。然后,我使用 DPAPI 对其进行加密,并将其存储在文本文件中以备后用。我遇到的问题是,当我解密文件时,它有时(经常)有随机的尾随字符,我无法弄清楚问题出在哪里。

以下是我用于加密和解密文件的函数

bool AuthManager::Encrypt(FString InString)
{
    const int32 Size = InString.Len();
    TArray<uint8> Data;
    Data.AddUninitialized(Size);
    StringToBytes(InString, Data.GetData(), Size);
    
    // Encrypt data from DATA_BLOB DataIn to DATA_BLOB DataOut.
    DATA_BLOB DataIn, DataOut;
    
    BYTE* PbDataInput = Data.GetData();
    const DWORD CBDataInput = strlen(reinterpret_cast<char*>(PbDataInput));
    
    DataIn.pbData = PbDataInput;    
    DataIn.cbData = CBDataInput;
    
    if(CryptProtectData(
         &DataIn,
         nullptr,
         nullptr,
         nullptr,
         nullptr,
         0,
         &DataOut))
    {
        const char* EncryptedTokenFile = "path\\to\\encryptedTokenFile.txt";
        
        std::ofstream EncryptedFile(EncryptedTokenFile, std::ios::out | std::ios::binary);
        
        EncryptedFile.write(reinterpret_cast<char*>(&DataOut.cbData), sizeof(DataOut.cbData));  
        EncryptedFile.write(reinterpret_cast<char*>(DataOut.pbData), DataOut.cbData); 
        EncryptedFile.close();
        LocalFree(DataOut.pbData);
    }
    else
    {
        UE_LOG(LogConsoleResponse, Error, TEXT("Encryption error using CryptProtectData."));
        return false;
    }
    return true;
}

//////////////////////////////////////////////////////////////////////
    
bool AuthManager::Decrypt(FString& OutString)
{
    const char* EncryptedTokenFile = "path\\to\\encryptedTokenFile.txt";
    
    std::ifstream ReadEncryptedFile(EncryptedTokenFile, std::ios::in | std::ios::binary);
    
    if(!ReadEncryptedFile.is_open())
    {
        UE_LOG(LogConsoleResponse, Error, TEXT("Cannot open %s. Please verify the file exists and is not read-protected."), *GetTokenFilePath());
        return false;
    }
    
    // Encrypt data from DATA_BLOB DataIn to DATA_BLOB DataOut.
    DATA_BLOB DataIn, DataOut;
    LPWSTR DataDesc = nullptr;
    
    ReadEncryptedFile.read(reinterpret_cast<char*>(&DataIn.cbData), sizeof(DataIn.cbData));  
    DataIn.pbData = new BYTE[DataIn.cbData];  
    ReadEncryptedFile.read(reinterpret_cast<char*>(DataIn.pbData), DataIn.cbData);
    
    // Begin unprotect phase.
    if (CryptUnprotectData(
            &DataIn,
            &DataDesc,
            nullptr,
            nullptr,
            nullptr,
            0,
            &DataOut))
    {

        // Convert byte output into FString
        OutString = BytesToString(DataOut.pbData, DataOut.cbData);
        
        UE_LOG(LogConsoleResponse, Display, TEXT("The OutString is: %s"), *OutString);
        
        LocalFree(DataOut.pbData);
        LocalFree(DataDesc);
    }
    else
    {
        UE_LOG(LogConsoleResponse, Error, TEXT("Decryption error using CryptUnprotectData."));
        return false;
    }
    
    return true;
}

我尝试增加或减少缓冲区中的字符数,但不一致

C++ 虚幻引擎5 DPAPI

评论

0赞 Botje 3/16/2023
对加密路径的调用需要终止 NUL 字节,这很可能并不总是正确的。改为设置。您似乎还假设输入字符串仅包含 ASCII,否则可能会产生比字符数 () 更多的字节。strlenCBDataInput = SizeStringToBytesSize
0赞 MashedPotato6587 3/17/2023
谢谢,是的,输入字符串应该永远是 ascii。但是,我应该如何对其进行虚拟防范,以防万一?

答: 暂无答案