加密/解密过程中加密++显式破坏?

时间:2017-03-02 01:10:06

标签: c++ encryption crypto++

我使用crypto ++编写了一些包装函数来加密/解密文件。我试着查看维基但可以找到我的答案。我想知道是否需要明确销毁我创建的对象?

我在维基中发现,传递给函数的某些对象会被破坏,但没有我确切使用的例子,所以我只想确定。

   CryptoPP::AutoSeededRandomPool prng;
   //Key generation
   byte key[AES::DEFAULT_KEYLENGTH];
   prng.GenerateBlock(key, sizeof(key));
   //IV generation
   byte iv[AES::BLOCKSIZE];
   prng.GenerateBlock(iv, sizeof(iv));



   //print key
   encoded.clear();
   StringSource(key, sizeof(key), true, new HexEncoder(new StringSink(encoded)));
   cout << "key: " << encoded << endl;
   cout << "Size of key: " << sizeof(key) << endl;

   //print iv
   encoded.clear();
   StringSource(iv, sizeof(iv), true, new HexEncoder(new StringSink(encoded)));
   cout << "iv: " << encoded << endl;
   cout << "Size of iv: " << sizeof(iv) << endl;

   //See function below
   encrypt_file(inFile, outFile, key, iv, err); 

   inFile.close();
   outFile.close();

在此函数中,字节数组由于某种原因被截断

Encrypt_file

    bool encrypt_file(std::ifstream& inFile,
       std::ofstream& outFile,
       const byte* key, const byte* iv,
       std::string& errMsg)
    {
       std::string encoded;
       //print key
       encoded.clear();
       StringSource(key, sizeof(key), true, new HexEncoder(new StringSink(encoded)));
       cout << "key: " << encoded << endl;
       cout << "Size of key: " << sizeof(key) << endl;

       //print iv
       encoded.clear();
       StringSource(iv, sizeof(iv), true, new HexEncoder(new StringSink(encoded)));
       cout << "iv: " << encoded << endl;
       cout << "Size of iv: " << sizeof(iv) << endl;
       try {
          CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption e;
          e.SetKeyWithIV(key, sizeof(key), iv);
          CryptoPP::FileSource(inFile, true, new CryptoPP::StreamTransformationFilter(e, new CryptoPP::FileSink(outFile)));
          inFile.close();
          outFile.close();
       }
       catch (CryptoPP::Exception& e) {
          errMsg = e.GetWhat();
          return false;
       }
       return true;
    }

输出:

key: 6574D7BDFD0DD3BC59CD3846D4A196A8
Size of key: 16
iv: 1B4ED692F91A32246B41F63F6B8C6EAA
Size of iv: 16
key: 6574D7BDFD0DD3BC
Size of key: 8
iv: 1B4ED692F91A3224
Size of iv: 8

2 个答案:

答案 0 :(得分:3)

不,你没有。您创建的对象具有automatic storage duration,这意味着它们的析构函数将在其作用域的末尾自动调用。此外,您使用new传递的参数将由Crypto ++对象拥有,其相应的析构函数将为您释放内存。它们属于接收器过滤器的类别,事实证明您也传递了所有权。有关详细信息,请参阅:

https://www.cryptopp.com/wiki/Pipelining#Ownership

基本上就是这样(超简化的例子):

#include <iostream>

struct Foo{};

class X
{
    Foo *p_;
public:
    X(Foo* p): p_(p) {}
    // we'd also need a copy ctor and copy assignment operator, ignored here
    ~X()
    {
        std::cout << "Releasing the memory...\n";
        delete p_;
    }
};

int main()
{
    X x(new Foo()); // sinking, no memory leak
}

Live on Coliru

我不得不说这是迄今为止我最不喜欢的软件设计风格。可以使用模板和mixin来实现类似的东西(阅读policy based design),没有指针浮动,没有明确的所有权。

答案 1 :(得分:2)

  

我使用crypto ++编写了一些包装函数来加密/解密文件。我试着查看维基但可以找到我的答案。我想知道是否需要明确销毁我创建的对象?

这取决于。来自 重要使用说明 下的README(列出了两个项目):

  
      
  1. 如果A的构造函数接受指向对象B的指针(除了诸如int和char之类的基本类型),那么A拥有B并将删除B   在A的破坏。如果A的构造函数引用了一个   对象B,然后调用者保留B的所有权,不应该   消灭它直到A不再需要它。

  2.   
  3. Crypto ++在类级别是线程安全的。这意味着您可以在多线程应用程序中安全地使用Crypto ++,但您必须提供   多个线程访问公共Crypto ++对象时的同步。

  4.   

这是你的代码。它看起来不错,不需要改变。但是我们可以通过它来完成(为了简洁,CryptoPP被删除了):

FileSource(inFile, true, new StreamTransformationFilter(encryptor, new FileSink(outFile)));
  1. 你有基于FileSource的堆栈。它是一个自动变量,当它超出范围时会被删除。它的样板C ++。
  2. 你有inFile。它是一个参考,你负责删除它。它的堆栈基于,当它超出调用者的范围时被删除。它的样板C ++。
  3. 您使用StreamTransformationFilter创建了new。它是一个指针,而FileSource拥有它。它将在FileSource析构函数运行时删除。管道是一种后天的品味。
  4. 你有encryptor。它是一个参考,你负责删除它。它的堆栈基于,当它超出范围时被删除。它的样板C ++。
  5. 您使用FileSink创建了new。它是一个指针,而StreamTransformationFilter拥有它。它将在StreamTransformationFilter析构函数运行时删除。管道是一种后天的品味。
  6. 你有outFile。它是一个参考,你负责删除它。它的堆栈基于,当它超出调用者的范围时被删除。它的样板C ++。
  7. 这些信息在维基上,但如果您不知道自己在寻找什么,那就很难找到。另请参阅维基上的Pipelining | Ownership

    相关,这看起来很可疑:

    e.SetKeyWithIV(key, sizeof(key), iv);
    

    因为key是一个声明为... byte key[], byte iv[] ...的函数参数,所以我认为decays to a pointer的大小为4(i686)或8(x86_64)。您应该使用类似下面的内容,它允许您指定数组的大小:

    bool encrypt_file(std::ifstream& inFile,
        std::ofstream& outFile,
        const byte* key, size_t ksize,
        const byte* iv, size_t vsize,
        std::string& errMsg)
    {
        ...
        e.SetKeyWithIV(key, ksize, iv);
        ...
    }
    

    所以,给定:

    byte key[AES::DEFAULT_KEYLENGTH];
    prng.GenerateBlock(key, sizeof(key));
    byte iv[AES::BLOCKSIZE];
    prng.GenerateBlock(iv, sizeof(iv));
    

    然后这样称呼它:

    encrypt_file(inFile, outFile, key, sizeof(key), iv, sizeof(iv), err);