Comet
Comet

Reputation: 288

crypto++ Sending IV to another Function but i get an error: StreamTransformationFilter: invalid PKCS #7 block padding found

Test Program to Encrypt using crypto++, then it sends the iv and message as IV::EncryptedMessage.

I am able to encrypt but get a padding error #7 when decrypting, I've searched for hours but can't find anyway to pass a std::string IV to crypto++.

I believe my error is in the decc function, where I use hexdecode?

string encc(string plain) {
    using namespace CryptoPP;

    AutoSeededRandomPool prng;


    SecByteBlock iv(AES::BLOCKSIZE);
    std::string sKey = "UltraSecretKeyPhrase";
    SecByteBlock key((const unsigned char*)(sKey.data()), sKey.size());
    prng.GenerateBlock(iv, iv.size());
    std::string cipher, recovered;

    try
    {
        CBC_Mode< AES >::Encryption e;
        e.SetKeyWithIV(key, key.size(), iv);

        StringSource s(plain, true,
            new StreamTransformationFilter(e,
                new StringSink(cipher)
            ) 
        ); 
    }
    catch (const Exception& e)
    {
        exit(1);
    }

    string ciphertxt, ivString;

    HexEncoder encoder(new FileSink(std::cout));
    encoder.Detach(new StringSink(ivString));
    encoder.Put(iv, iv.size());
    encoder.MessageEnd();

    encoder.Detach(new StringSink(ciphertxt));
    encoder.Put((const byte*)&cipher[0], cipher.size());
    encoder.MessageEnd();

    string toSend = ivString + "::" + ciphertxt;
    return toSend;
}

string decc(string toDec) {
    using namespace CryptoPP;

    std::string sKey = "UltraSecretKeyPhrase";
    SecByteBlock key((const unsigned char*)(sKey.data()), sKey.size());
    
    
    std::string recovered;
    string str1 = "::";

   
    size_t found = toDec.find(str1);
    if (found != string::npos) {

        std::string sIv = toDec.substr(0, found);
        std::string encMessage = toDec.substr(found + 2, toDec.length());
        
        cout << endl << "IV: " << sIv << endl << "Encoded Msg: " << encMessage << endl;
        
        string iv;
        HexDecoder decoder;

        decoder.Attach(new StringSink(iv));
        decoder.Put((byte*)sIv.data(), sIv.size());
        decoder.MessageEnd();
        try
        {
            CBC_Mode< AES >::Decryption d;
            d.SetKeyWithIV(key.data(), key.size(), (byte *)iv.data(), AES::BLOCKSIZE);

            StringSource s(encMessage, true,
                new StreamTransformationFilter(d,
                    new StringSink(recovered)
                )
            );
            return recovered;
        }
        catch (const Exception& e)
        {
            std::cerr << e.what() << std::endl;
            exit(1);
        }
    }
    else return NULL;
}

int main(){
    string hh = encc("this is encoded");
    cout << hh << endl;
    string gg = decc(hh);
    cout << gg << endl;
    return 0;
}

Just can't seem to use the right words for google :)

Upvotes: 1

Views: 266

Answers (2)

Comet
Comet

Reputation: 288

I Decoded the hex of the IV but never the actual encrypted message. Of course I seen it after I posted smh...

This is a functional example of crypto++ encode and decode functions for anyone looking for it.


string encc(string plain) {
    using namespace CryptoPP;

    AutoSeededRandomPool prng;


    SecByteBlock iv(AES::BLOCKSIZE);
    std::string sKey = "UltraSecretKeyPhrase";
    SecByteBlock key((const unsigned char*)(sKey.data()), sKey.size());
    prng.GenerateBlock(iv, iv.size());
    std::string cipher, recovered;

    try
    {
        CBC_Mode< AES >::Encryption e;
        e.SetKeyWithIV(key, key.size(), iv);

        StringSource s(plain, true,
            new StreamTransformationFilter(e,
                new StringSink(cipher)
            ) 
        ); 
    }
    catch (const Exception& e)
    {
        exit(1);
    }

    string ciphertxt, ivString;

    HexEncoder encoder(new FileSink(std::cout));
    encoder.Detach(new StringSink(ivString));
    encoder.Put(iv, iv.size());
    encoder.MessageEnd();

    encoder.Detach(new StringSink(ciphertxt));
    encoder.Put((const byte*)&cipher[0], cipher.size());
    encoder.MessageEnd();

    string toSend = ivString + "::" + ciphertxt;
    return toSend;
}

string decc(string toDec) {
    using namespace CryptoPP;

    std::string sKey = "UltraSecretKeyPhrase";
    SecByteBlock key((const unsigned char*)(sKey.data()), sKey.size());
    
    
    std::string recovered;
    string str1 = "::";

   
    size_t found = toDec.find(str1);
    if (found != string::npos) {

        std::string sIv = toDec.substr(0, found);
        std::string encMessageHex = toDec.substr(found + 2);
        
        cout << endl << "IV: " << sIv << endl << "Encoded Msg: " << encMessageHex << endl;
        
        string iv, encMessage;
        HexDecoder decoder, msgDecoder;

        decoder.Attach(new StringSink(iv));
        decoder.Put((byte*)sIv.data(), sIv.size());
        decoder.MessageEnd();
        // Forgot to decode encrypted message hex. added here
        decoder.Attach(new StringSink(encMessage));
        decoder.Put((byte*)encMessageHex.data(), encMessageHex.size());
        decoder.MessageEnd();
        try
        {
            CBC_Mode< AES >::Decryption d;
            d.SetKeyWithIV(key.data(), key.size(), (byte *)iv.data(), AES::BLOCKSIZE);

            StringSource s(encMessage, true,
                new StreamTransformationFilter(d,
                    new StringSink(recovered)
                )
            );
            return recovered;
        }
        catch (const Exception& e)
        {
            std::cerr << e.what() << std::endl;
            exit(1);
        }
    }
    else return NULL;
}

int main(){
    string hh = encc("this is encoded");
    cout << hh << endl;
    string gg = decc(hh);
    cout << gg << endl;
    return 0;
}

Upvotes: 1

Arty
Arty

Reputation: 16747

You have a decoding bug, instead of toDec.substr(found + 2, toDec.length()) you should write toDec.substr(found + 2, toDec.length() - (found + 2)), because .substr() accepts number of symbols, not the end-position.

Maybe there are other bugs, but this definitely will break decoding process due to having garbarge inside encrypted message.

You may also just use toDec.substr(found + 2), i.e. don't specify the count, if second param is not specified then substring is taken till the very end of string.

Upvotes: 1

Related Questions