我是Crypto++的新手,希望将我在网上找到的文本加密代码“转换”为Crypto++文件加密。基本上,一个图像文件只是一堆文本,需要用块来读取,对吗?
我想读取一个图像文件并用CryptoPP::AES加密它
void encryptImage(std::filesystem::path const& file) {
std::ifstream inpf(file.string().c_str(), std::ios::binary);
CryptoPP::AutoSeededRandomPool rnd;
int keyLength = CryptoPP::AES::DEFAULT_KEYLENGTH; // 16 bytes = 128 bit key
int defBlockSize = CryptoPP::AES::BLOCKSIZE;
// Generate a random key
CryptoPP::byte key[CryptoPP::AES::DEFAULT_KEYLENGTH];
rnd.GenerateBlock(key, CryptoPP::AES::DEFAULT_KEYLENGTH);
// Generate a random IV
CryptoPP::byte iv[CryptoPP::AES::BLOCKSIZE];
rnd.GenerateBlock(iv, CryptoPP::AES::BLOCKSIZE);
char plainText[] = "Hello! How are you.";
int messageLen = (int)strlen(plainText) + 1;
//encrypt
CryptoPP::CFB_Mode<CryptoPP::AES>::Encryption cfbEncryption(key, CryptoPP::AES::DEFAULT_KEYLENGTH, iv);
cfbEncryption.ProcessData((CryptoPP::byte*)plainText, (CryptoPP::byte*)plainText, messageLen);
}如果我正确理解这段代码,它会设置一个随机密钥和一个随机IV (不知道这意味着什么),并使用CFB_MODE::Encryption方法加密来自plainText变量的给定文本。
我现在的问题是..。如何将此代码更改为加密作为参数的文件,并使用std::ifstream而不是文本读取文件?
发布于 2020-08-30 22:42:05
如果我正确理解这段代码,它会设置一个随机密钥和一个随机IV (不知道这意味着什么),并使用CFB_MODE::Encryption方法加密来自plainText变量的给定文本。
正确,该代码生成大小为128位的随机AES密钥和大小为128位的随机初始化向量(IV)。可以调整密钥大小以增加加密强度(也可以有256位密钥),而IV的大小必须等于AES块大小(128位),这与密钥大小无关。因此,在这种情况下,两者都是128位只是巧合。
分组密码模式被设置为CFB (参考文献 )。分组密码模式的动机是,我们不希望在输入的不同位置出现相同的数据块进行相同的加密。否则,就有可能从加密的数据中推断出原始数据的某些结构,如链接文章中的图像文件示例所示。为了避免这个问题,块密码模式以某种方式将当前块中的纯文本与前一个块组合在一起。CFB的数学细节在链接文章中得到了解释,但基本上它将使用前一个块的加密来异或明文。
第一个块是特例,因为它没有以前的块。IV用作第一个块的“前一个块”(因此IV需要等于块大小)。IV不需要是秘密的(与密钥不同),但是应该为每条加密的消息随机选择它,以防止攻击者推断消息的结构信息。
如何将此代码更改为加密作为参数的文件,并使用std::ifstream而不是文本读取文件?
要将加密应用于文件,可以使用FileSource和FileSink类,这些类由crypto++提供:
// Type aliases for key and IV
using aes_key_t = std::array<CryptoPP::byte, CryptoPP::AES::DEFAULT_KEYLENGTH>;
using aes_iv_t = std::array<CryptoPP::byte, CryptoPP::AES::BLOCKSIZE>;
void encrypt(const aes_key_t &key, const aes_iv_t &iv,
const std::string &filename_in, const std::string &filename_out) {
CryptoPP::CFB_Mode<CryptoPP::AES>::Encryption cipher{};
cipher.SetKeyWithIV(key.data(), key.size(), iv.data());
std::ifstream in{filename_in, std::ios::binary};
std::ofstream out{filename_out, std::ios::binary};
CryptoPP::FileSource{in, /*pumpAll=*/true,
new CryptoPP::StreamTransformationFilter{
cipher, new CryptoPP::FileSink{out}}};
}这将“泵”所有数据从源到接收器,应用给定的转换。在这种情况下,源是输入文件,接收器是输出文件,转换是加密。
通常,不鼓励通过new进行手动内存管理,而倾向于使用智能指针或其他更高级别的抽象。然而,crypto++ API似乎早于这一指导方针,因此我们无法使用new,然后再信任crypto++为我们分配这些分配。
您也可以将文件名直接传递给FileSource和FileSink (参考文献,参考文献),但是由于您专门询问了std::ifstream,所以我在示例中使用了它。
加密和解密的完整示例:
#include <cryptopp/files.h>
#include <cryptopp/modes.h>
#include <cryptopp/osrng.h>
#include <fstream>
#include <iostream>
using aes_key_t = std::array<CryptoPP::byte, CryptoPP::AES::DEFAULT_KEYLENGTH>;
using aes_iv_t = std::array<CryptoPP::byte, CryptoPP::AES::BLOCKSIZE>;
void encrypt(const aes_key_t &key, const aes_iv_t &iv,
const std::string &filename_in, const std::string &filename_out) {
CryptoPP::CFB_Mode<CryptoPP::AES>::Encryption cipher{};
cipher.SetKeyWithIV(key.data(), key.size(), iv.data());
std::ifstream in{filename_in, std::ios::binary};
std::ofstream out{filename_out, std::ios::binary};
CryptoPP::FileSource{in, /*pumpAll=*/true,
new CryptoPP::StreamTransformationFilter{
cipher, new CryptoPP::FileSink{out}}};
}
void decrypt(const aes_key_t &key, const aes_iv_t &iv,
const std::string &filename_in, const std::string &filename_out) {
CryptoPP::CFB_Mode<CryptoPP::AES>::Decryption cipher{};
cipher.SetKeyWithIV(key.data(), key.size(), iv.data());
std::ifstream in{filename_in, std::ios::binary};
std::ofstream out{filename_out, std::ios::binary};
CryptoPP::FileSource{in, /*pumpAll=*/true,
new CryptoPP::StreamTransformationFilter{
cipher, new CryptoPP::FileSink{out}}};
}
int main(int argc, char **argv) {
std::cout << CryptoPP::AES::BLOCKSIZE << std::endl;
CryptoPP::AutoSeededRandomPool rng{};
// Generate a random key
aes_key_t key{};
rng.GenerateBlock(key.data(), key.size());
// Generate a random IV
aes_iv_t iv{};
rng.GenerateBlock(iv.data(), iv.size());
// encrypt
encrypt(key, iv, "abc.jpg", "abc_encrypted");
// decrypt
decrypt(key, iv, "abc_encrypted", "abc_decrypted.jpg");
return 0;
}https://stackoverflow.com/questions/61313699
复制相似问题