使用管道加密文件

Use of Pipelines to encrypt a file

我刚刚开始使用 crypto++,我对 piplenes 以及如何使用它们加密文件有疑问。

我想使用 AES 加密文件。

1.)只做就够了吗:

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

2.) 如果我有一个巨大的输入文件,这种方法会自动加密块中的文件吗?

3.) 如果不存在,是否会自动创建输出文件?

编辑:

好的,我用我的方法把它炒了。

2.) 问题仍然存在,我有一个新问题:

我可以告诉它跳过文件的前 24 个字节吗?

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

关闭。 AuthenticatedEncryptionFilter 将被强制转换为 FileSinkbool pumpAll 参数。所以你需要:

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

另请参阅手册中的 FileSource on the Crypto++ wiki. And the FileSource Class Reference 可能也会感兴趣。


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

是的。在内部,Crypto++ 将 "block" 或 "chunk" 处理 4096 字节,IIRC。最近关于它的讨论出现在 ios locking up during encryption.

的邮件列表中

post 中提供了 allows you to do the blocking 的程序。如果需要,您可以使用它来限制处理,更新进度条或让出处理器的地方。转载如下。


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

是的。 FileSource 只是一个 std::ifstream 包装器,而 FileSink 只是一个 std::ofstream 包装器。

同样,这里是 wiki 页面:


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

是的。在这种情况下,使用 bool pumpAll 并将其设置为 false。然后做类似的事情:

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;
}

或者,您可以:

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

另请参阅手册中的 FileSource Class ReferenceSkipBufferedTransformation 的一部分; PumpAllSource.

的一部分

还有涵盖 EAX 模式和经过身份验证的{en|de}加密过滤器的 wiki 页面。参见:

甚至还有一个关于使用 Java-like Init/Update/Final 的页面:


下面的程序使用CFB_Mode<AES>,但很容易换成另一种密码和模式。它还演示了如何将对象放在堆栈上并在管道中使用它们,而不是使用 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;
}