使用Crypto ++ FileSource散列大块文件

时间:2018-10-27 09:06:56

标签: c++ hash cryptography crypto++

我有一个需要散列的大文件,但是如果我直接从文件中散列它,则我的内存将受到限制。我想散列2个步骤而不是1个步骤。例如,我首先使用算法CRC32对文件进行哈希处理,然后存储在字符串中。然后执行第二步以再次哈希到SHA256中。

目前,我成功完成了第一步的哈希文件。但是它会占用内存,如果内存不足,最终会返回错误或崩溃。

为了使在循环中使用cpu的程度不高。我决定选择1048576字节(1MB)作为块。在此测试中,我的控制台未返回crc32哈希。

CRC32 hash;
std::string str;
FileSource file("D:/1.exe", false, new HashFilter(hash, new HexEncoder(new StringSink(str))), true);
while (!file.SourceExhausted())
{
    file.Pump(1048576);
}
std::cout << str;
getchar();
return 0;

1 个答案:

答案 0 :(得分:0)

  

我有一个需要散列的大文件,但是如果我直接从文件中散列它,则我的内存将受到限制。所以我想分2步而不是1步哈希。例如我首先使用算法CRC32对文件进行散列并存储在字符串中。然后执行第二步以再次哈希到SHA256 ...

我认为您应该使用ChannelSwitch并让库提供过滤器。默认情况下,该库使用4KB的块,它应使您保持在内存上限以下。

ChannelSwitch可以将源数据馈送到多个过滤器,因此您只需读取一次数据。您不必担心编写自己的"tee"-like filter

首先,修改程序以使用ChannelSwitch并使用名为data.bin的文件。您将在下面创建文件:

$ cat test.cxx

#include "cryptlib.h"
#include "channels.h"
#include "filters.h"
#include "files.h"
#include "sha.h"
#include "crc.h"
#include "hex.h"

#include <string>
#include <iostream>

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

    try
    {
        std::string s1, s2;
        CRC32 crc;
        SHA1 sha1;

        HashFilter f1(crc, new HexEncoder(new StringSink(s1)));
        HashFilter f2(sha1, new HexEncoder(new StringSink(s2)));

        ChannelSwitch cs;
        cs.AddDefaultRoute(f1);
        cs.AddDefaultRoute(f2);

        FileSource("data.bin", true /*pumpAll*/, new Redirector(cs));

        std::cout << "Filename: " << "data.bin" << std::endl;
        std::cout << "   CRC32: " << s1 << std::endl;
        std::cout << "    SHA1: " << s2 << std::endl;
    }
    catch(const Exception& ex)
    {
        std::cerr << ex.what() << std::endl;
    }

  return 0;
}

接下来,创建一个非常大的文件:

$ dd if=/dev/urandom of=data.bin bs=1M count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 5.48884 s, 196 MB/s

下一步,编译并运行程序:

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

$ time ./test.exe
Filename: data.bin
   CRC32: 20F45F3E
    SHA1: F0857F8E46112BB08A04D5CE51BDBEA0C4539032

real    0m4.430s
user    0m4.269s
sys     0m0.156s

最后,如Pumping Data | Low Memory所述,使用Bash shell模拟内存不足的情况。注意,我们需要12 MB的空间来运行可执行文件。否则libc.so.6会被链接加载程序映射失败。剩下大约4 MB的RAM用于程序和数据。

$ (ulimit -v 16368; ./test.exe)
Filename: data.bin
   CRC32: 20F45F3E
    SHA1: F0857F8E46112BB08A04D5CE51BDBEA0C4539032