簡體   English   中英

使用 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM