encryption/decryption 期间 Crypto++ 显式销毁?
Crypto++ explicit destruction during encryption/decryption?
我使用 crypto++ 向 encrypt/decrypt 文件编写了一些包装函数。我尝试查看维基,但可以找到我的答案。我想知道我是否需要显式销毁我创建的对象?
我在 wiki 中发现传递给函数的一些对象会为您销毁,但没有我确切使用的示例,所以我只是想确定一下。
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
不,你不知道。您创建的对象具有 automatic storage duration,这意味着它们的析构函数将在其作用域结束时自动调用。此外,您通过 new
传递的参数将归 Crypto++ 对象所有,它们相应的析构函数将为您释放内存。它们属于 sink 或 filter 的类别,结果你也传递了所有权。欲了解更多详情,请参阅:
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
}
我不得不说,这是迄今为止我最不喜欢的软件设计风格。人们可以使用模板和混入来实现类似的事情(阅读 policy based design),而不需要指针在没有明确所有权的情况下四处浮动。
I wrote some wrapper functions to encrypt/decrypt files using crypto++. I tried looking in the wiki but could find my answer. I am wondering if I need to explicitly destroy my objects that are created?
视情况而定。来自Important Usage Notes下的README(列出两项):
If a constructor for A takes a pointer to an object B (except primitive types such as int and char), then A owns B and will delete B
at A's destruction. If a constructor for A takes a reference to an
object B, then the caller retains ownership of B and should not
destroy it until A no longer needs it.
Crypto++ is thread safe at the class level. This means you can use Crypto++ safely in a multithreaded application, but you must provide
synchronization when multiple threads access a common Crypto++ object.
这是您的代码。它看起来不错,不需要更改。但是为了完整起见,我们可以遍历它(为简洁起见,删除了 CryptoPP
):
FileSource(inFile, true, new StreamTransformationFilter(encryptor, new FileSink(outFile)));
- 你有基于堆栈的
FileSource
。它是一个自动变量,当它超出范围时会被删除。它的样板 C++。
- 你有
inFile
。它是参考,您有责任删除它。它是基于堆栈的,当它超出调用者的范围时就会被删除。它的样板 C++。
- 您已使用
new
创建了 StreamTransformationFilter
。它是一个指针,FileSource
拥有它。当 FileSource
析构函数运行时,它将被删除。管道是一种后天的品味。
- 你有
encryptor
。它是参考,您有责任删除它。它基于堆栈,超出范围时将被删除。它的样板 C++。
- 您已使用
new
创建了 FileSink
。它是一个指针,StreamTransformationFilter
拥有它。当 StreamTransformationFilter
析构函数运行时,它将被删除。管道是一种后天的品味。
- 你有
outFile
。它是参考,您有责任删除它。它是基于堆栈的,当它超出调用者的范围时就会被删除。它的样板 C++。
信息在 wiki 上,但如果您不知道要查找什么,则很难找到。另请参阅维基上的 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);
我使用 crypto++ 向 encrypt/decrypt 文件编写了一些包装函数。我尝试查看维基,但可以找到我的答案。我想知道我是否需要显式销毁我创建的对象?
我在 wiki 中发现传递给函数的一些对象会为您销毁,但没有我确切使用的示例,所以我只是想确定一下。
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
不,你不知道。您创建的对象具有 automatic storage duration,这意味着它们的析构函数将在其作用域结束时自动调用。此外,您通过 new
传递的参数将归 Crypto++ 对象所有,它们相应的析构函数将为您释放内存。它们属于 sink 或 filter 的类别,结果你也传递了所有权。欲了解更多详情,请参阅:
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
}
我不得不说,这是迄今为止我最不喜欢的软件设计风格。人们可以使用模板和混入来实现类似的事情(阅读 policy based design),而不需要指针在没有明确所有权的情况下四处浮动。
I wrote some wrapper functions to encrypt/decrypt files using crypto++. I tried looking in the wiki but could find my answer. I am wondering if I need to explicitly destroy my objects that are created?
视情况而定。来自Important Usage Notes下的README(列出两项):
If a constructor for A takes a pointer to an object B (except primitive types such as int and char), then A owns B and will delete B at A's destruction. If a constructor for A takes a reference to an object B, then the caller retains ownership of B and should not destroy it until A no longer needs it.
Crypto++ is thread safe at the class level. This means you can use Crypto++ safely in a multithreaded application, but you must provide synchronization when multiple threads access a common Crypto++ object.
这是您的代码。它看起来不错,不需要更改。但是为了完整起见,我们可以遍历它(为简洁起见,删除了 CryptoPP
):
FileSource(inFile, true, new StreamTransformationFilter(encryptor, new FileSink(outFile)));
- 你有基于堆栈的
FileSource
。它是一个自动变量,当它超出范围时会被删除。它的样板 C++。 - 你有
inFile
。它是参考,您有责任删除它。它是基于堆栈的,当它超出调用者的范围时就会被删除。它的样板 C++。 - 您已使用
new
创建了StreamTransformationFilter
。它是一个指针,FileSource
拥有它。当FileSource
析构函数运行时,它将被删除。管道是一种后天的品味。 - 你有
encryptor
。它是参考,您有责任删除它。它基于堆栈,超出范围时将被删除。它的样板 C++。 - 您已使用
new
创建了FileSink
。它是一个指针,StreamTransformationFilter
拥有它。当StreamTransformationFilter
析构函数运行时,它将被删除。管道是一种后天的品味。 - 你有
outFile
。它是参考,您有责任删除它。它是基于堆栈的,当它超出调用者的范围时就会被删除。它的样板 C++。
信息在 wiki 上,但如果您不知道要查找什么,则很难找到。另请参阅维基上的 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);