Ben
Ben

Reputation: 199

Use of Pipelines to encrypt a file

I have just startet working with crypto++ and i have a question about the piplenes and how to use them to encrypt a file.

I want to use AES to encrypt a file.

1.)Would it be enough to just do:

EAX<AES>::Encryption encryptor;
encryptor.SetKeyWithIV(derived.data(), 16, ivb, ivb.size());
FileSource f("source", new AuthenticatedEncryptionFilter(encryptor,new FileSink("deststination")));

2.) If i have a huge input file, will this approach automaticly encrypt the files in blocks?

3.) Would this automaticly create the output file if it is not there?

EDIT:

Ok, i got it to wok with my approch.

The 2.) Question remains and i have a new one:

Can I tell it to skip the first 24 bytes of the file?

Upvotes: 1

Views: 419

Answers (1)

jww
jww

Reputation: 102426

EAX<AES>::Encryption encryptor;
encryptor.SetKeyWithIV(derived.data(), 16, ivb, ivb.size());
FileSource f("source", new AuthenticatedEncryptionFilter(encryptor,new FileSink("deststination")));

Close. The AuthenticatedEncryptionFilter will be coerced to the bool pumpAll parameter of FileSink. So you need:

FileSource f("source", true, new AuthenticatedEncryptionFilter(encryptor,new FileSink("deststination")));

Also see FileSource on the Crypto++ wiki. And the FileSource Class Reference from the manual might be of interest, too.


If i have a huge input file, will this approach automatically encrypt the files in blocks?

Yes. Internally, Crypto++ will "block" or "chunk" the processing in 4096-bytes, IIRC. A recent discussion about it occurred on the mailing list at ios locking up during encryption.

A program that allows you to do the blocking is provided in the post. You can use it to throttle the processing, a place to update a progress bar or yield the processor, if needed. Its reproduced below.


Would this automatically create the output file if it is not there?

Yes. The FileSource is just a std::ifstream wrapper, while a FileSink is just a std::ofstream wrapper.

Again, here are the wiki pages:


Can I tell it to skip the first 24 bytes of the file?

Yes. In this case, use bool pumpAll and set it to false. Then do something like:

FileSource fs("source", false, new AuthenticatedEncryptionFilter(...));
fs.Skip(24);

size_t remaining = <size of file>;
size_t BLOCK_SIZE = 512;
while(remaining && !fs.SourceExhausted())
{    
    const unsigned int req = STDMIN(remaining, BLOCK_SIZE);
    fs.Pump(req);
    fs.Flush(false);

    remaining -= req;
}

Or, you can:

FileSource fs("source", false, new AuthenticatedEncryptionFilter(...));
fs.Skip(24);
fs.PumpAll();

Also see FileSource Class Reference in the manual. Skip is part of BufferedTransformation; and PumpAll is part of Source.


There are also wiki pages covering EAX mode and the authenticated {en|de}cryption filters. See:

There's even a page on using a Java-like Init/Update/Final at:


The program below uses CFB_Mode<AES>, but its easy enough to swap in another cipher and mode. It also demonstrates how to place objects on the stack and use them in a pipeline rather than creating them on the heap with new.

int main(int argc, char* argv[])
{
  static const unsigned int BIG_SIZE = 2U * 1024U * 1024U;    
  static const unsigned int BLOCK_SIZE = 4096U;

  try
    {
      SecByteBlock key(32);
      OS_GenerateRandomBlock(false, key.data(), key.size());

      // cout << "Key: ";
      // ArraySource as(key.data(), key.size(), true, new HexEncoder(new FileSink(cout)));
      // cout << endl;

      CFB_Mode<AES>::Encryption enc;
      enc.SetKeyWithIV(key.data(), key.size(), key.data());

      MeterFilter meter;
      StreamTransformationFilter stf(enc);

      FileSource source("/dev/zero", false);
      FileSink sink("zero.enc");

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

      unsigned int remaining = BIG_SIZE;
      while(remaining && !source.SourceExhausted())
      {
        if(remaining % (1024) == 0)
        {
          cout << "Processed: " << meter.GetTotalBytes() << endl;    
        }

        const unsigned int req = STDMIN(remaining, BLOCK_SIZE);
        source.Pump(req);
        source.Flush(false);

        remaining -= req;
    }
  }
  catch(const Exception& ex)
  {
    cerr << ex.what() << endl;
  }

  return 0;
}

Upvotes: 1

Related Questions