【问题标题】:Why does RAD Studio CreateBlobStream with CryptUnprotectData return extra characters?为什么带有 CryptUnprotectData 的 RAD Studio CreateBlobStream 返回额外的字符?
【发布时间】:2018-03-30 20:03:26
【问题描述】:

我正在编写一个从 Chrome 中提取密码的恢复应用。它有一个 GUI,所以我使用了他们的 SQLite 包装器,它同时使用了 SQLConnection 和 SQLQuery。这是我的代码片段:

//Create our blob stream
TStream *Stream2 = SQLQuery1->CreateBlobStream(SQLQuery1->FieldByName("password_value"), bmRead);
//Get our blob size
int size = Stream2->Size;
//Create our buffer
char* pbDataInput = new char[size+1];
//Adding null terminator to buffer
memset(pbDataInput, 0x00, sizeof(char)*(size+1));
//Write to our buffer
Stream2->ReadBuffer(pbDataInput, size);
DWORD cbDataInput = size;

DataOut.pbData = pbDataInput;
DataOut.cbData = cbDataInput;

LPWSTR pDescrOut = NULL;
//Decrypt password
CryptUnprotectData( &DataOut,
        &pDescrOut,
        NULL,
        NULL,
        NULL,
        0,
        &DataVerify);

//Output password
UnicodeString password = (UnicodeString)(char*)DataVerify.pbData;
passwordgrid->Cells[2][i] = password;

输出数据看起来不错,除了它的行为好像我的空终止符出了问题。以下是每一行的输出:

我读过

CryptUnprotectData 的 Windows 文档:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa382377.aspx

CreateBlobStream 的 Embarcadero 文档:

http://docwiki.embarcadero.com/Libraries/en/Data.DB.TDataSet.CreateBlobStream

内存集:

http://www.cplusplus.com/reference/cstring/memset/

【问题讨论】:

    标签: c++ winapi c++builder


    【解决方案1】:

    您的读取和解密调用仅对原始字节进行操作,它们对字符串一无所知,也不关心它们。您添加到 pbDataInput 的空终止符从未使用过,因此请去掉它:

    //Get our blob size
    int size = Stream2->Size;
    //Create our buffer
    char* pbDataInput = new char[size];
    //Write to our buffer
    Stream2->ReadBuffer(pbDataInput, size);
    DWORD cbDataInput = size;
    ...
    delete[] pbDataInput;
    delete Stream2;
    

    现在,当将pbData 分配给password 时,您将pbData 转换为char*,因此UnicodeString 构造函数将数据解释为以null 结尾的ANSI 字符串并将其转换为UTF-16使用系统默认的 ANSI 代码页,这可能是对非 ASCII 字符的有损转换。这真的是你想要的吗?

    如果是这样,并且如果解密的数据实际上不是以 null 结尾的,则必须向 UnicodeString 构造函数指定字符数:

    UnicodeString password( (char*)DataVerify.pbData, DataVerify.cbData );
    

    另一方面,如果解密后的输出已经是 UTF-16,则需要将 pbData 转换为 wchar_t*

    UnicodeString password = (wchar_t*)DataVerify.pbData;
    

    或者,如果不是以 null 结尾的:

    UnicodeString password( (wchar_t*)DataVerify.pbData, DataVerify.cbData / sizeof(wchar_t) );
    

    【讨论】:

    • 谢谢,我明白了它与空终止符有关。支持你的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 2011-04-28
    • 1970-01-01
    • 2016-05-13
    • 2010-12-05
    • 1970-01-01
    相关资源
    最近更新 更多