Reputation: 1051
My question/problem might be a bit newbie regarding this field, but I cannot find any solution or clear explanation to achieve what I want.
I must store and use the hash values as BYTE instead of STRING because of the size. ( it causes me troubles in other areas )
The function generates an MD5 hash for a file, used on 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;
}
This seems to achieve the desired result, because the size of result string is 40 and the size of data is 8 which is a massive reduction in size for me.
However I do not see this as a good solution and I am pretty sure that there must but an easier and cleaner way of doing this.
Any examples are much appreciated.
Upvotes: 2
Views: 583
Reputation: 102205
I must store and use the hash values as BYTE instead of STRING because of the size...
You are almost there.
Both StringSource
and ArraySink
can handle byte
arrays. You just need to use alternate constuctors. Also see StringSource
and ArraySink
on the Crypto++ wiki.
I would modify the code similar to the following. I'm using C++11 so I don't have 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;
}
And then compile. I'm working from the cryptopp/
directory in my home directory:
$ g++ ./test.cxx ./libcryptopp.a -o test.exe
$
And finally:
$ ./test.exe
Filename: ./cryptlib.h
Digest: 626047BC8770BE942B26B3AD6CBD3781
In the code above, here are the sources and sinks wrapping the byte array:
StringSource(digest, sizeof(digest) ...);
ArraySink(digest, size);
If you were storing into a std::string
like in How to easily apply Crypto++ hash functions?, here are the sources and sinks wrapping the std::string
. They are different constructors.
std::string digest;
...
StringSource(digest, ...);
StringSink(digest);
Upvotes: 2