为什么 RAD Studio CreateBlobStream with CryptUnprotectData return 额外字符?
Why does RAD Studio CreateBlobStream with CryptUnprotectData return extra characters?
我正在编写一个从 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;
输出数据看起来不错,只是它的行为好像我的空终止符出了问题。这是每一行的输出:
已阅读
Windows CryptUnprotectData
的文档:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa382377.aspx
CreateBlobStream
的 Embarcadero 文档:
http://docwiki.embarcadero.com/Libraries/en/Data.DB.TDataSet.CreateBlobStream
内存集:
您的读取和解密调用仅对原始字节进行操作,它们对字符串一无所知,也不关心它们。您要添加到 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 字符串,并将使用系统默认的 ANSI 代码页将其转换为 UTF-16,这对于非 ASCII 字符可能是一种有损转换。那是你真正想要的吗?
如果是这样,并且如果解密的数据实际上不是空终止的,则必须向 UnicodeString
构造函数指定字符数:
UnicodeString password( (char*)DataVerify.pbData, DataVerify.cbData );
另一方面,如果解密后的输出已经是 UTF-16 格式,则需要将 pbData
转换为 wchar_t*
:
UnicodeString password = (wchar_t*)DataVerify.pbData;
或者,如果不是空终止的:
UnicodeString password( (wchar_t*)DataVerify.pbData, DataVerify.cbData / sizeof(wchar_t) );
我正在编写一个从 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;
输出数据看起来不错,只是它的行为好像我的空终止符出了问题。这是每一行的输出:
已阅读
Windows CryptUnprotectData
的文档:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa382377.aspx
CreateBlobStream
的 Embarcadero 文档:
http://docwiki.embarcadero.com/Libraries/en/Data.DB.TDataSet.CreateBlobStream
内存集:
您的读取和解密调用仅对原始字节进行操作,它们对字符串一无所知,也不关心它们。您要添加到 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 字符串,并将使用系统默认的 ANSI 代码页将其转换为 UTF-16,这对于非 ASCII 字符可能是一种有损转换。那是你真正想要的吗?
如果是这样,并且如果解密的数据实际上不是空终止的,则必须向 UnicodeString
构造函数指定字符数:
UnicodeString password( (char*)DataVerify.pbData, DataVerify.cbData );
另一方面,如果解密后的输出已经是 UTF-16 格式,则需要将 pbData
转换为 wchar_t*
:
UnicodeString password = (wchar_t*)DataVerify.pbData;
或者,如果不是空终止的:
UnicodeString password( (wchar_t*)DataVerify.pbData, DataVerify.cbData / sizeof(wchar_t) );