std::ifstream 将文件读取为 BYTE(无符号字符)而非字符
std::ifstream read file as BYTE (unsigned char) not char
我正在使用 Microsoft 的 CNG 密码术 API 来计算文件的哈希值,到目前为止一切正常,除了计算的哈希值与使用外部第 3 方程序计算的哈希值相比是错误的。
我不是 100% 确定,但我认为问题是我将文件读入 signed char
数组而不是 BYTE
(无符号字符)数组。
下面的代码是我现在读取文件的方式:(注意:我省略了错误检查代码)
std::ifstream file;
file.open("sample.txt", std::ifstream::binary | std::ifstream::in | std::ifstream::ate);
const int file_length = file.tellg();
char* data = new char[file_length];
file.seekg(file.beg);
file.read(data, file_length);
上面代码的问题是数据被读入有符号字符数组,但加密函数需要 unsigned char / BYTE
,我猜这就是我计算的哈希值错误的原因。
下面的代码是我想做的,但它不起作用(添加评论),因为 ifstream::read()
方法需要 char
数组而不是 unsigned char / BYTE
std::ifstream file;
file.open("sample.txt", std::ifstream::binary | std::ifstream::in | std::ifstream::ate);
const int file_length = file.tellg();
PBYTE data = new BYTE[file_length];
file.seekg(file.beg);
file.read(data, file_length); // error PBYTE is incompatibe with char*
所以我的问题是:如何将数据读取为 BYTE
而不是 char
我需要使用 CreateFile
API 还是有办法使用 std::ifstream
?
也许还有其他原因导致计算的哈希值错误,我不知道是否告诉我。
编辑:
下面是计算给定文件名的 SHA256 哈希的完整工作代码,但哈希是错误的。 (即与使用 3rd 方哈希实用程序完成的不同)
#include <windows.h>
#include <bcrypt.h>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <fstream>
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
std::string ByteToHex(PBYTE data, size_t len)
{
std::stringstream ss;
ss << std::hex << std::setfill('0') << std::uppercase;
for (size_t i = 0; i < len; ++i)
{
ss << std::setw(2) << static_cast<short>(data[i]);
}
return ss.str();
}
int main()
{
BCRYPT_ALG_HANDLE hAlg = nullptr;
BCRYPT_HASH_HANDLE hHash = nullptr;
DWORD cbHash, cbObject, cbData;
PBYTE pbHash, pbObject;
NTSTATUS status = STATUS_UNSUCCESSFUL;
std::ifstream file;
file.open("sample.exe", std::ifstream::binary | std::ifstream::in | std::ifstream::ate);
const int file_length = file.tellg();
if (!file.is_open())
{
abort();
}
PBYTE data = new BYTE[file_length];
file.seekg(file.beg);
file.read(reinterpret_cast<char*>(data), file_length);
status = BCryptOpenAlgorithmProvider(
&hAlg,
BCRYPT_SHA256_ALGORITHM,
nullptr,
0);
if (NT_SUCCESS(status))
{
status = BCryptGetProperty(
hAlg,
BCRYPT_OBJECT_LENGTH,
reinterpret_cast<PBYTE>(&cbObject),
sizeof(DWORD),
&cbData,
0);
}
else
{
abort();
}
pbObject = reinterpret_cast<PBYTE>(
HeapAlloc(GetProcessHeap(), 0, cbObject));
if (!pbObject)
{
abort();
}
if (NT_SUCCESS(status))
{
status = BCryptGetProperty(
hAlg,
BCRYPT_HASH_LENGTH,
reinterpret_cast<PBYTE>(&cbHash),
sizeof(DWORD),
&cbData,
0);
}
else
{
abort();
}
pbHash = reinterpret_cast<PBYTE>(
HeapAlloc(GetProcessHeap(), 0, cbHash));
if (!pbHash)
{
abort();
}
if (NT_SUCCESS(status))
{
status = BCryptCreateHash(
hAlg,
&hHash,
pbObject,
cbObject,
nullptr,
0,
0);
}
else
{
abort();
}
if (NT_SUCCESS(status))
{
status = BCryptHashData(
hHash,
(PBYTE)(data),
sizeof(data),
0);
}
else
{
abort();
}
if (NT_SUCCESS(status))
{
status = BCryptFinishHash(
hHash,
pbHash,
cbHash,
0);
}
else
{
abort();
}
std::cout << ByteToHex(pbHash, cbHash).c_str();
delete[] data;
if(hAlg) BCryptCloseAlgorithmProvider(hAlg, 0);
if(hHash) BCryptDestroyHash(hHash);
if(pbHash) HeapFree(GetProcessHeap(), 0, pbHash);
if(pbObject) HeapFree(GetProcessHeap(), 0, pbObject);
return 0;
}
当调用 read
或 write
时,这是认为可以使用 reinterpret_cast
的少数情况之一。在某些情况下,没有其他可行的解决方案。
所以对于你的情况:
file.read(reinterpret_cast<char*>(data), file_length);
我正在使用 Microsoft 的 CNG 密码术 API 来计算文件的哈希值,到目前为止一切正常,除了计算的哈希值与使用外部第 3 方程序计算的哈希值相比是错误的。
我不是 100% 确定,但我认为问题是我将文件读入 signed char
数组而不是 BYTE
(无符号字符)数组。
下面的代码是我现在读取文件的方式:(注意:我省略了错误检查代码)
std::ifstream file;
file.open("sample.txt", std::ifstream::binary | std::ifstream::in | std::ifstream::ate);
const int file_length = file.tellg();
char* data = new char[file_length];
file.seekg(file.beg);
file.read(data, file_length);
上面代码的问题是数据被读入有符号字符数组,但加密函数需要 unsigned char / BYTE
,我猜这就是我计算的哈希值错误的原因。
下面的代码是我想做的,但它不起作用(添加评论),因为 ifstream::read()
方法需要 char
数组而不是 unsigned char / BYTE
std::ifstream file;
file.open("sample.txt", std::ifstream::binary | std::ifstream::in | std::ifstream::ate);
const int file_length = file.tellg();
PBYTE data = new BYTE[file_length];
file.seekg(file.beg);
file.read(data, file_length); // error PBYTE is incompatibe with char*
所以我的问题是:如何将数据读取为 BYTE
而不是 char
我需要使用 CreateFile
API 还是有办法使用 std::ifstream
?
也许还有其他原因导致计算的哈希值错误,我不知道是否告诉我。
编辑: 下面是计算给定文件名的 SHA256 哈希的完整工作代码,但哈希是错误的。 (即与使用 3rd 方哈希实用程序完成的不同)
#include <windows.h>
#include <bcrypt.h>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <fstream>
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
std::string ByteToHex(PBYTE data, size_t len)
{
std::stringstream ss;
ss << std::hex << std::setfill('0') << std::uppercase;
for (size_t i = 0; i < len; ++i)
{
ss << std::setw(2) << static_cast<short>(data[i]);
}
return ss.str();
}
int main()
{
BCRYPT_ALG_HANDLE hAlg = nullptr;
BCRYPT_HASH_HANDLE hHash = nullptr;
DWORD cbHash, cbObject, cbData;
PBYTE pbHash, pbObject;
NTSTATUS status = STATUS_UNSUCCESSFUL;
std::ifstream file;
file.open("sample.exe", std::ifstream::binary | std::ifstream::in | std::ifstream::ate);
const int file_length = file.tellg();
if (!file.is_open())
{
abort();
}
PBYTE data = new BYTE[file_length];
file.seekg(file.beg);
file.read(reinterpret_cast<char*>(data), file_length);
status = BCryptOpenAlgorithmProvider(
&hAlg,
BCRYPT_SHA256_ALGORITHM,
nullptr,
0);
if (NT_SUCCESS(status))
{
status = BCryptGetProperty(
hAlg,
BCRYPT_OBJECT_LENGTH,
reinterpret_cast<PBYTE>(&cbObject),
sizeof(DWORD),
&cbData,
0);
}
else
{
abort();
}
pbObject = reinterpret_cast<PBYTE>(
HeapAlloc(GetProcessHeap(), 0, cbObject));
if (!pbObject)
{
abort();
}
if (NT_SUCCESS(status))
{
status = BCryptGetProperty(
hAlg,
BCRYPT_HASH_LENGTH,
reinterpret_cast<PBYTE>(&cbHash),
sizeof(DWORD),
&cbData,
0);
}
else
{
abort();
}
pbHash = reinterpret_cast<PBYTE>(
HeapAlloc(GetProcessHeap(), 0, cbHash));
if (!pbHash)
{
abort();
}
if (NT_SUCCESS(status))
{
status = BCryptCreateHash(
hAlg,
&hHash,
pbObject,
cbObject,
nullptr,
0,
0);
}
else
{
abort();
}
if (NT_SUCCESS(status))
{
status = BCryptHashData(
hHash,
(PBYTE)(data),
sizeof(data),
0);
}
else
{
abort();
}
if (NT_SUCCESS(status))
{
status = BCryptFinishHash(
hHash,
pbHash,
cbHash,
0);
}
else
{
abort();
}
std::cout << ByteToHex(pbHash, cbHash).c_str();
delete[] data;
if(hAlg) BCryptCloseAlgorithmProvider(hAlg, 0);
if(hHash) BCryptDestroyHash(hHash);
if(pbHash) HeapFree(GetProcessHeap(), 0, pbHash);
if(pbObject) HeapFree(GetProcessHeap(), 0, pbObject);
return 0;
}
当调用 read
或 write
时,这是认为可以使用 reinterpret_cast
的少数情况之一。在某些情况下,没有其他可行的解决方案。
所以对于你的情况:
file.read(reinterpret_cast<char*>(data), file_length);