从磁盘而不是内存加密和解密文件?

时间:2018-03-07 04:01:48

标签: c++ encryption crypto++

当我尝试使用AES算法加密和解密250MB文件时,我收到以下错误。当我尝试使用小于250的数据集时,我能够获得输出。

enter image description here

1 个答案:

答案 0 :(得分:-2)

来自评论:

string cipher, encoded, recovered;
FileSource file("C:/Users/sai/desktop/RA/250.avi", true, new StringSink(plain));

取决于几个因素,这可能会也可能不会起作用。在桌面或服务器上,您应该没有问题,因为它将有大量的RAM和交换文件。

在移动设备上,如果文件很大,它可能会死亡。如果它死了,那么问题可能是因为StringSink是一个内存中的字符串但设备的内存不足。

来自评论:

  

...我是否需要将文件分成块然后加密和解密?

不,你不应该把文件分成块。 FileSource将为您完成。如果我没记错的话,它会将数据分成4096个块。您可能需要做的是从StringSink切换到FileSink

另请参阅Crypto ++ wiki上的Pumping Data | Encryption。这是提供的样本:

inline bool EndOfFile(const FileSource& file)
{
  std::istream* stream = const_cast<FileSource&>(file).GetStream();
  return stream->eof();
}

int main(int argc, char* argv[])
{
  try
  {
      byte key[AES::DEFAULT_KEYLENGTH]={}, iv[AES::BLOCKSIZE]={};
      CTR_Mode<AES>::Encryption encryptor;
      encryptor.SetKeyWithIV(key, sizeof(key), iv);

      MeterFilter meter;
      StreamTransformationFilter filter(encryptor);

      FileSource source("plain.bin", false);
      FileSink sink("cipher.bin");

      source.Attach(new Redirector(filter));
      filter.Attach(new Redirector(meter));
      meter.Attach(new Redirector(sink));

      const word64 BLOCK_SIZE = 4096;
      word64 processed = 0;

      while(!EndOfFile(source) && !source.SourceExhausted())
      {
        source.Pump(BLOCK_SIZE);
        filter.Flush(false);

        processed += BLOCK_SIZE;

        if (processed % (1024*1024*10) == 0)
          cout << "Processed: " << meter.GetTotalBytes() << endl;
      }

      // Signal there is no more data to process.
      // The dtor's will do this automatically.
      filter.MessageEnd();
  }
  catch(const Exception& ex)
  {
    cerr << ex.what() << endl;
  }

  return 0;
}

来自TITLE:

  

[如何]从磁盘而不是内存加密和解密文件?

尝试以下内容。您的代码缺少加密或解密对象,因此请务必在实际代码中包含一个。

FileSource file("C:/Users/sai/desktop/RA/250.avi", true, new FileSink("C:/Users/sai/desktop/RA/250.avi.enc"));

或者,您可以使用显示如何手动提取数据的代码。

来自评论:

int start_s = clock();

另请参阅Crypto ++ wiki上的Benchmarks | Sample Program。这是提供的样本:

const double runTimeInSeconds = 3.0;
const double cpuFreq = 2.7 * 1000 * 1000 * 1000;

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

    SecByteBlock key(16);
    prng.GenerateBlock(key, key.size());

    CTR<AES>::Encryption cipher;
    cipher.SetKeyWithIV(key, key.size(), key);

    const int BUF_SIZE = RoundUpToMultipleOf(2048U,
        dynamic_cast<StreamTransformation&>(cipher).OptimalBlockSize());

    AlignedSecByteBlock buf(BUF_SIZE);
    prng.GenerateBlock(buf, buf.size());

    double elapsedTimeInSeconds;
    unsigned long i=0, blocks=1;

    ThreadUserTimer timer;
    timer.StartTimer();

    do
    {
        blocks *= 2;
        for (; i<blocks; i++)
            cipher.ProcessString(buf, BUF_SIZE);
        elapsedTimeInSeconds = timer.ElapsedTimeAsDouble();
    }
    while (elapsedTimeInSeconds < runTimeInSeconds);

    const double bytes = static_cast<double>(BUF_SIZE) * blocks;
    const double ghz = cpuFreq / 1000 / 1000 / 1000;
    const double mbs = bytes / elapsedTimeInSeconds / 1024 / 1024;
    const double cpb = elapsedTimeInSeconds * cpuFreq / bytes;

    std::cout << cipher.AlgorithmName() << " benchmarks..." << std::endl;
    std::cout << "  " << ghz << " GHz cpu frequency"  << std::endl;
    std::cout << "  " << cpb << " cycles per byte (cpb)" << std::endl;
    std::cout << "  " << mbs << " MiB per second (MiB)" << std::endl;   

    return 0;
}