使用 FileSource 和 FileSink 将 AES IV 转换为文件
AES IV into file with FileSource and FileSink
我需要使用 crypto++ 加密大文件(多 GB)。我设法在帮助我创建以下 2 个函数的文档中找到了一个示例:
bool AESEncryptFile(const std::string& clearfile, const std::string& encfile, const std::string& key) {
try {
byte iv[CryptoPP::AES::BLOCKSIZE] = {};
CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption encryptor;
encryptor.SetKeyWithIV((unsigned char*)key.c_str(), CryptoPP::AES::DEFAULT_KEYLENGTH, iv);
CryptoPP::StreamTransformationFilter filter(encryptor);
CryptoPP::FileSource source(clearfile.c_str(), false);
CryptoPP::FileSink sink(encfile.c_str());
source.Attach(new CryptoPP::Redirector(filter));
filter.Attach(new CryptoPP::Redirector(sink));
const CryptoPP::word64 BLOCK_SIZE = 4096;
CryptoPP::word64 processed = 0;
while (!EndOfFile(source) && !source.SourceExhausted()) {
source.Pump(BLOCK_SIZE);
filter.Flush(false);
processed += BLOCK_SIZE;
}
filter.MessageEnd();
return true;
} catch (const CryptoPP::Exception& ex) {
return false;
}
}
bool AESDecryptFile(const std::string& encfile, const std::string& clearfile, const std::string& key) {
try {
byte iv[CryptoPP::AES::BLOCKSIZE] = {};
CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption decryptor;
decryptor.SetKeyWithIV((unsigned char*)key.c_str(), CryptoPP::AES::DEFAULT_KEYLENGTH, iv);
CryptoPP::StreamTransformationFilter filter(decryptor);
CryptoPP::FileSource source(encfile.c_str(), false);
CryptoPP::FileSink sink(clearfile.c_str());
source.Attach(new CryptoPP::Redirector(filter));
filter.Attach(new CryptoPP::Redirector(sink));
const CryptoPP::word64 BLOCK_SIZE = 4096;
CryptoPP::word64 processed = 0;
while (!EndOfFile(source) && !source.SourceExhausted()) {
source.Pump(BLOCK_SIZE);
filter.Flush(false);
processed += BLOCK_SIZE;
}
.
filter.MessageEnd();
return true;
} catch (const CryptoPP::Exception& ex) {
return false;
}
}
效果很好。在 8 GB 的文件上,我使用的内存非常少。
但是正如您所看到的,IV 是(暂时为空)硬编码的,我想:
- 加密时,将其放在文件末尾。
- 解密时:从文件中获取 IV 以初始化解密器。
有没有办法用 crypto++ 做到这一点,或者我应该手动处理它 after/before enc/decryption 过程?
感谢所有不同的评论,这就是我设法做到的。根据 @Sam Mason 的建议,我将 iv 放在文件的开头:
所以在开始加密之前,我将 iv 放在文件的开头:
CryptoPP::ArraySource(iv, sizeof(iv), true,
new CryptoPP::Redirector(sink)
);
// Encrypt
然后在解密时我像这样取回 IV :
unsigned char iv[CryptoPP::AES::BLOCKSIZE];
CryptoPP::ArraySink ivSink(iv, sizeof(iv));
source.Attach(new CryptoPP::Redirector(ivSink));
source.Pump(CryptoPP::AES::BLOCKSIZE);
// Decrypt
未来注意事项reader:不要像我的 OP 中那样使用空 IV,而是随机生成一个,例如:
CryptoPP::AutoSeededRandomPool prng;
unsigned char iv[CryptoPP::AES::BLOCKSIZE];
prng.GenerateBlock(iv, sizeof(iv));
我需要使用 crypto++ 加密大文件(多 GB)。我设法在帮助我创建以下 2 个函数的文档中找到了一个示例:
bool AESEncryptFile(const std::string& clearfile, const std::string& encfile, const std::string& key) {
try {
byte iv[CryptoPP::AES::BLOCKSIZE] = {};
CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption encryptor;
encryptor.SetKeyWithIV((unsigned char*)key.c_str(), CryptoPP::AES::DEFAULT_KEYLENGTH, iv);
CryptoPP::StreamTransformationFilter filter(encryptor);
CryptoPP::FileSource source(clearfile.c_str(), false);
CryptoPP::FileSink sink(encfile.c_str());
source.Attach(new CryptoPP::Redirector(filter));
filter.Attach(new CryptoPP::Redirector(sink));
const CryptoPP::word64 BLOCK_SIZE = 4096;
CryptoPP::word64 processed = 0;
while (!EndOfFile(source) && !source.SourceExhausted()) {
source.Pump(BLOCK_SIZE);
filter.Flush(false);
processed += BLOCK_SIZE;
}
filter.MessageEnd();
return true;
} catch (const CryptoPP::Exception& ex) {
return false;
}
}
bool AESDecryptFile(const std::string& encfile, const std::string& clearfile, const std::string& key) {
try {
byte iv[CryptoPP::AES::BLOCKSIZE] = {};
CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption decryptor;
decryptor.SetKeyWithIV((unsigned char*)key.c_str(), CryptoPP::AES::DEFAULT_KEYLENGTH, iv);
CryptoPP::StreamTransformationFilter filter(decryptor);
CryptoPP::FileSource source(encfile.c_str(), false);
CryptoPP::FileSink sink(clearfile.c_str());
source.Attach(new CryptoPP::Redirector(filter));
filter.Attach(new CryptoPP::Redirector(sink));
const CryptoPP::word64 BLOCK_SIZE = 4096;
CryptoPP::word64 processed = 0;
while (!EndOfFile(source) && !source.SourceExhausted()) {
source.Pump(BLOCK_SIZE);
filter.Flush(false);
processed += BLOCK_SIZE;
}
.
filter.MessageEnd();
return true;
} catch (const CryptoPP::Exception& ex) {
return false;
}
}
效果很好。在 8 GB 的文件上,我使用的内存非常少。 但是正如您所看到的,IV 是(暂时为空)硬编码的,我想:
- 加密时,将其放在文件末尾。
- 解密时:从文件中获取 IV 以初始化解密器。
有没有办法用 crypto++ 做到这一点,或者我应该手动处理它 after/before enc/decryption 过程?
感谢所有不同的评论,这就是我设法做到的。根据 @Sam Mason 的建议,我将 iv 放在文件的开头:
所以在开始加密之前,我将 iv 放在文件的开头:
CryptoPP::ArraySource(iv, sizeof(iv), true,
new CryptoPP::Redirector(sink)
);
// Encrypt
然后在解密时我像这样取回 IV :
unsigned char iv[CryptoPP::AES::BLOCKSIZE];
CryptoPP::ArraySink ivSink(iv, sizeof(iv));
source.Attach(new CryptoPP::Redirector(ivSink));
source.Pump(CryptoPP::AES::BLOCKSIZE);
// Decrypt
未来注意事项reader:不要像我的 OP 中那样使用空 IV,而是随机生成一个,例如:
CryptoPP::AutoSeededRandomPool prng;
unsigned char iv[CryptoPP::AES::BLOCKSIZE];
prng.GenerateBlock(iv, sizeof(iv));