Encrypt big char* using std::string with Crypto++

蓝咒 提交于 2020-02-08 04:19:28

问题


I am new with Crypto++. I want to using Crypto++ library to encrypt/decrypt a large byte array in C++. The data can be anything, so asume its binary format. First, I tried with "byte array" (char * or char[]).

byte PlainText[] = {
  'H','e','l','l','o',' ',
  'W','o','r','l','d',
  0x0,0x0,0x0,0x0,0x0
};

byte key[ AES::DEFAULT_KEYLENGTH ];
::memset( key, 0x01, AES::DEFAULT_KEYLENGTH );

// Encrypt
ECB_Mode< AES >::Encryption Encryptor( key, sizeof(key) );

byte cbCipherText[AES::BLOCKSIZE];

Encryptor.ProcessData( cbCipherText, PlainText, sizeof(PlainText) );

We use ProcessData() to encrypt the plain text, since it allows us to receive the result in a single line of code. Next, we enter a DMZ, and then decrypt the cipher text.

// Decrypt

ECB_Mode< AES >::Decryption Decryptor( key, sizeof(key) );

byte cbRecoveredText[AES::BLOCKSIZE];

Decryptor.ProcessData( cbRecoveredText, cbCipherText, sizeof(cbCipherText) );

The code above work perfect with small data (16KB). But it doesn't work with large data because "is not multiple of block size". Then, I think about using StreamTransformationFilter, which can automatic do the padding job for me. So I tried to encrypt and decrypt a std::string with encryptString() and decryptString() like below:

string  encryptString(string plain, byte key[], int sizeKey, byte iv[], int sizeIV){
    string cipher;
    try{
        CBC_Mode< AES >::Encryption e;
        e.SetKeyWithIV(key, sizeKey, iv, sizeIV);

        // The StreamTransformationFilter removes
        //  padding as required.
        StringSource s(plain, true,
            new StreamTransformationFilter(e,
            new StringSink(cipher)
            ) // StreamTransformationFilter
            ); // StringSource

#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{
        CBC_Mode< AES >::Decryption d;
        d.SetKeyWithIV(key, sizeKey, iv, sizeIV);

        StringSource s(cipher, true,
            new StreamTransformationFilter(d,
            new StringSink(reco)
            ) // StreamTransformationFilter
            ); // StringSource

#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;
    }
}

They are worked for large text file too. But, wait, my goal is encrypt/decrypt ANY byte array. And sometime they aren't string. So I think about wrap the above two function to work with char *.

//wrap encryptString()
char* encrypt(char * plainText, byte key[], int sizeKey, byte iv[], int sizeIV){
    string cipher = encryptString(plainText, key, sizeKey, iv, sizeIV);
    FileUtil::writeFile("ss1.txt", cipher, cipher.length());
    long len = cipher.size() + 1;
     char * writable = new  char[len];
    std::copy(cipher.begin(), cipher.end(), writable);
    writable[len] = '\0'; 

    // don't forget to free the string after finished using it
    //delete[] writable;
    return writable;
}

//wrap decryptString()
char* decrypt(char * cipher,  byte key[], int sizeKey, byte iv[], int sizeIV){
    long len = strlen(cipher);
    string recovered = decryptString(cipher, key, sizeKey, iv, sizeIV);
    char * writable = new char[recovered.size() + 1];
    std::copy(recovered.begin(), recovered.end(), writable);
    writable[recovered.size()] = '\0'; // don't forget the terminating 0

    // don't forget to free the string after finished using it
    //delete[] writable;
    return writable;
}

The result is: When I read 1MB of text to encrypt() function, write the encrypted string "cipher" to "ss1.txt", its 1MB too. But to "writable", its only a part of "cipher" (about 1KB), and decrypted result is a part of original text too. Seem like '\0' was met somewhere and its terminated my char array? I feel like going around now. Is there a way to using Crypto++ with (any) large byte (binary) array?

Additionally, I want to avoid using FileSource (Crypto++), because it doesn't allow me to save the encrypted value to variable.

来源:https://stackoverflow.com/questions/40586525/encrypt-big-char-using-stdstring-with-crypto

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!