将哈希输出作为 BYTE 而不是 std::string?

Hash output as BYTE instead of std::string?

我的 question/problem 可能是这个领域的新手,但我找不到任何解决方案或明确的解释来实现我想要的。

问题

由于大小的原因,我必须将散列值存储和使用为 BYTE 而不是 STRING。 (这给我带来了其他方面的麻烦)

该函数为文件生成 MD5 散列值,用于 windows OS。

当前代码

std::string MD5Checksum(const path &file)
{
    std::string result;
    try
    {
        CryptoPP::Weak::MD5 md5;

        CryptoPP::HashFilter f5(md5, new CryptoPP::HexEncoder(new CryptoPP::StringSink(result)));

        CryptoPP::ChannelSwitch cs;
        cs.AddDefaultRoute(f5);

        CryptoPP::FileSource ss(file.string().c_str(), true /*pumpAll*/, new CryptoPP::Redirector(cs));
    }
    catch (CryptoPP::Exception const& exception)
    {
      // 
    }

    return result;
}

我测试了什么

std::string MD5Checksum(const path &file)
{
    std::string result;
    try
    {
        CryptoPP::Weak::MD5 md5;

        CryptoPP::HashFilter f5(md5, new CryptoPP::HexEncoder(new CryptoPP::StringSink(result)));

        CryptoPP::ChannelSwitch cs;
        cs.AddDefaultRoute(f5);

        CryptoPP::FileSource ss(file.string().c_str(), true /*pumpAll*/, new CryptoPP::Redirector(cs));
    }
    catch (CryptoPP::Exception const& exception)
    {
        //
    }

    string decoded;
    CryptoPP::StringSource ss(result, true /*pumpAll*/, new CryptoPP::StringSink(decoded));
    const BYTE* data = reinterpret_cast<const BYTE*>(decoded.data());
    printf(L"sizeof result: %d, sizeof data: %d"), sizeof(result), sizeof(data));

    return result;
}

这似乎达到了预期的结果,因为结果字符串的大小是 40,数据的大小是 8,这对我来说是一个巨大的减少。

但是我不认为这是一个好的解决方案,我很确定必须有一种更简单、更清洁的方法来做到这一点。

非常感谢任何示例。

I must store and use the hash values as BYTE instead of STRING because of the size...

你快到了。

StringSourceArraySink 都可以处理 byte 数组。您只需要使用替代构造函数。另请参阅 Crypto++ wiki 上的 StringSource and ArraySink

我会修改类似下面的代码。我正在使用 C++11,所以我没有 std::path:

$ cat test.cxx
#include "cryptlib.h"
#include "filters.h"
#include "files.h"
#include "hex.h"

#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
#include "md5.h"

#include <iostream>

#if defined(CRYPTOPP_NO_GLOBAL_BYTE)
using CryptoPP::byte;
#endif

bool MD5Checksum(const std::string &file, byte* digest, size_t size)
{
    using namespace CryptoPP;

    try
    {
        Weak::MD5 md5;
        FileSource(file.c_str(), true /*pumpAll*/,
            new HashFilter(md5, new ArraySink(digest, size)));
    }
    catch (Exception const& exception)
    {
        return false;
    }

    return true;
}

int main(int argc, char* argv[])
{
    using namespace CryptoPP;

    std::string filename = (argc >= 2 ? argv[1] : "./cryptlib.h");
    byte digest[Weak::MD5::DIGESTSIZE];

    if (MD5Checksum(filename, digest, sizeof(digest)))
    {
        std::cout << "Filename: " << filename << std::endl;
        std::cout << "Digest: ";
        StringSource(digest, sizeof(digest), true, new HexEncoder(new FileSink(std::cout)));
        std::cout << std::endl;
    }
    else
    {
        std::cerr << "Failed to calculate digest of " << filename << std::endl;
        std::exit(1);
    }

    return 0;
}

然后编译。我正在我的主目录中的 cryptopp/ 目录中工作:

$ g++ ./test.cxx ./libcryptopp.a -o test.exe
$

最后:

$ ./test.exe
Filename: ./cryptlib.h
Digest: 626047BC8770BE942B26B3AD6CBD3781

在上面的代码中,这里是包装字节数组的源和汇:

StringSource(digest, sizeof(digest) ...);
ArraySink(digest, size);

如果您像在 中那样存储到 std::string 中,这里是包裹 std::string 的源和汇。他们是不同的构造函数。

std::string digest;
...

StringSource(digest, ...);
StringSink(digest);