【问题标题】:std::ifstream read file as BYTE (unsigned char) not charstd::ifstream 将文件读取为 BYTE (unsigned char) 而不是 char
【发布时间】:2019-04-08 07:13:05
【问题描述】:

我正在使用 Microsoft 的 CNG Cryptography API 来计算文件的哈希值,到目前为止一切正常,除了计算的哈希值与使用外部 3rd 方程序计算的哈希值相比是错误的。

我不是 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;
}

【问题讨论】:

    标签: c++ file byte cng


    【解决方案1】:

    当调用readwrite 时,这是认为可以使用reinterpret_cast 的少数情况之一。在某些情况下,没有其他可行的解决方案。

    所以对于你的情况:

    file.read(reinterpret_cast<char*>(data), file_length);
    

    【讨论】:

    • 计算的hash还是错的,和我读成char一样,你知道为什么计算的hash错了吗?
    • @zebanovich 也许问题不在于阅读?也许问题出在数据上?也许问题出在有计算上?请发布一个关于此的问题。
    • 谢谢!您的解决方案有效,我发现我的代码的问题是我只散列了第一个 BYTE 而不是条目 file_lenght :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-18
    相关资源
    最近更新 更多