![](/img/trans.png)
[英]How to encrypt/decrypt data using RSA OAEP SHA-256 in Crypto++
[英]Effecient way for encrypt large data using Crypto++
我正在寻找一种使用 Crypto++ 加密/解密大文件(一些 GB)的解决方案。 几天前,我正在考虑在这个问题中使用 StringSource ,将整个文件读入一个字符数组,然后使用 CTR 模式对其进行加密/解密。
将字符串加密为字符串
string encryptString(string plain, byte key[], int sizeKey, byte iv[], int sizeIV){
string cipher;
try{
CTR_Mode< AES >::Encryption e;
e.SetKeyWithIV(key, sizeKey, iv, sizeIV);
StringSource s(plain, true,
new StreamTransformationFilter(e,
new StringSink(cipher)
)
);
#if 0
StreamTransformationFilter filter(e);
filter.Put((const byte*)plain.data(), plain.size());
filter.MessageEnd();
const size_t ret = filter.MaxRetrievable();
cipher.resize(ret);
filter.Get((byte*)cipher.data(), cipher.size());
#endif
return cipher;
}
catch (const CryptoPP::Exception& e)
{
cerr << e.what() << endl;
return NULL;
}
}
将字符串解密为字符串
string decryptString(string cipher, byte key[], int sizeKey, byte iv[], int sizeIV){
string reco;
try{
CTR_Mode< AES >::Decryption d;
d.SetKeyWithIV(key, sizeKey, iv, sizeIV);
StringSource s(cipher, true,
new StreamTransformationFilter(d,
new StringSink(reco)
)
);
#if 0
StreamTransformationFilter filter(e);
filter.Put((const byte*)plain.data(), plain.size());
filter.MessageEnd();
const size_t ret = filter.MaxRetrievable();
cipher.resize(ret);
filter.Get((byte*)cipher.data(), cipher.size());
#endif
return reco;
}
catch (const CryptoPP::Exception& e)
{
cerr << e.what() << endl;
return reco;
}
}
将加密字符串包裹在上面
char* encrypt(char * plainText, byte key[], int sizeKey, byte iv[], int sizeIV, long len){
string ss(plainText, len);
long lengSS = ss.length();
string cipher = encryptString(ss, key, sizeKey, iv, sizeIV);
len = cipher.size();
char * writable = new char[len];
std::copy(cipher.begin(), cipher.end(), writable);
writable[len] = '\0';
return writable;
}
将上面的解密字符串包裹起来
char* decrypt(char * cipher, byte key[], int sizeKey, byte iv[], int sizeIV, long len){
string ss(cipher, len);
long lengSS = ss.length();
string recovered = decryptString(ss, key, sizeKey, iv, sizeIV);
//FileUtil::writeStringToFile("d2.txt", recovered);
char * writable = new char[recovered.size() ];
std::copy(recovered.begin(), recovered.end(), writable);
writable[recovered.size() ] = '\0';
return writable;
}
主要的
int main(int argc, char* argv[])
{
AutoSeededRandomPool prng;
byte key[AES::DEFAULT_KEYLENGTH] = { '1', '2', '3', '4', '5', '6', '7', '8', '1', '2', '3', '4', '5', '6', '7', '8' };
byte iv[AES::BLOCKSIZE] = { '8', '7', '6', '5', '4', '3', '2', '1', '8', '7', '6', '5', '4', '3', '2', '1' };
//prng.GenerateBlock(iv, sizeof(iv));
char* pdata = "CTR encrypt mode 1234567890";
char * sourceFileName = "1MB.txt";
char * targetFileName = "1MB.aes.crpp.txt";
/*
Looking for parameters.
param 0: e to encrypt. d to decrypt
param 1: sourceFileName
param 2: targetFileName
*/
if (argc > 1){
char * action = argv[1];
sourceFileName = argv[2];
targetFileName = argv[3];
long size = 0;
char * pdata = FileUtil::readAllByte(sourceFileName, size);
string ext = getExtension(sourceFileName);
char * result1 = NULL;
if (strcmp(action, "e") == 0){
result1 = encrypt(pdata, key, sizeof(key), iv, sizeof(iv), size);
}
else if (strcmp(action, "d") == 0){
result1 = decrypt(pdata, key, sizeof(key), iv, sizeof(iv), size);
}
FileUtil::writeFile(targetFileName, result1, size);
//FileUtil::writeStringToFile(targetFileName, recovered1);
}
else{
cout << "Missing/Invalid params" << endl;
}
return 0;
}
现在这个解决方案可以加密/解密大小高达数百 MB 的文件。 但是当我将它与 1GB 文本文件一起使用时,出现错误:
Unhandled exception at 0x74DFA6F2 in AES-CRPP.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x00AFE480.
在线:
char*encrypt(...){
string ss(data, len)
...
}
我有 8GB 的 RAM,它看起来像是读取 1GB 的字符并将其转换为字符串导致错误。 在另一个问题中,jww 在底部给了我一个提示,但我无法让它工作。 是否有使用 Crypto++ 加密大字节(char)数组的解决方案
关于在此处使用 FileSource 文档:在此处输入链接描述代码示例:
EAX< Blowfish >::Encryption e1;
e1.SetKeyWithIV(key, key.size(), iv, sizeof(iv));
CryptoPP::FileSource fs1(ofilename.c_str(), true,
new AuthenticatedEncryptionFilter(e1,
new FileSink(efilename.c_str())
));
EAX< Blowfish >::Decryption d2;
d2.SetKeyWithIV(key, key.size(), iv, sizeof(iv));
CryptoPP::FileSource fs2(efilename.c_str(), true,
new AuthenticatedDecryptionFilter(d2,
new FileSink(rfilename.c_str()),
AuthenticatedDecryptionFilter::THROW_EXCEPTION
));
它不允许我将输出密码导出到临时 char * 变量,而不是直接保存到文件中。 当然我可以等待文件到文件加密完成,然后再次将输出文件读入内存,但它看起来很糟糕。
正如您所说,您想加密大文件,同时在 RAM 中消耗更少的内存。 所以你可以使用在crypto++
使用的管道。 请参考此链接https://www.cryptopp.com/wiki/Pumping_Data
现在,您将只看到如何限制流程的大小。 所以如果你想做大文件的加密。 最好是逐块加密大文件。 所以你可以使用crypto++
密码块技术。
您可以使用StreamTransformationFilter
因为它会自动以块为单位加密文件。
我已经复制了代码来做同样的事情。 以下代码将使用管道过程加密大文件。 它不会占用您计算机中超过 10MB 的 RAM。
bool Widget::optimize_enc(const char *filename){
try
{
string pwd="qwertyuiopasdfgh";
const char* enc="out.aes";
byte iv[ CryptoPP::CIPHER::BLOCKSIZE ];
memset( iv, 0x01, CryptoPP::CIPHER::BLOCKSIZE );
CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption Encryptor((byte*)&pwd[0], pwd.size(), iv);
StreamTransformationFilter f1(Encryptor, new FileSink(enc));
ChannelSwitch cs;
cs.AddDefaultRoute(f1);
FileSource(filename, true /*pumpAll*/, new Redirector(cs));
}
catch(const Exception& ex)
{
std::cerr << ex.what() << std::endl;
return false;
}
return true;
}
请记住, passphrase
的长度应为16
个字节。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.