2

I have the followind piece of code that encrypts and decrypts the message.

QString AesUtils::encrypt(QString message, QString aesKey)
{
    string plain = message.toStdString();
    qDebug() << "Encrypt" << plain.data() << " " << plain.size();
    string ciphertext;
    // Hex decode symmetric key:
    HexDecoder decoder;
    string stdAesKey = aesKey.toStdString();
    decoder.Put((byte*)stdAesKey.data(), aesKey.size());
    decoder.MessageEnd();
    word64 size = decoder.MaxRetrievable();
    char *decodedKey = new char[size];
    decoder.Get((byte *)decodedKey, size);
    // Generate Cipher, Key, and CBC
    byte key[ AES::MAX_KEYLENGTH ], iv[ AES::BLOCKSIZE ];
    StringSource( reinterpret_cast<const char *>(decodedKey), true,
                  new HashFilter(*(new SHA256), new ArraySink(key, AES::MAX_KEYLENGTH)) );
    memset( iv, 0x00, AES::BLOCKSIZE );
    CBC_Mode<AES>::Encryption Encryptor( key, sizeof(key), iv );
    StringSource( plain, true, new StreamTransformationFilter( Encryptor,
                  new HexEncoder(new StringSink( ciphertext )) ) );
    return QString::fromStdString(ciphertext);
}

QString AesUtils::decrypt(QString message, QString aesKey)
{
    string plain;
    string encrypted = message.toStdString();

    // Hex decode symmetric key:
    HexDecoder decoder;
    string stdAesKey = aesKey.toStdString();
    decoder.Put( (byte *)stdAesKey.data(), aesKey.size() );
    decoder.MessageEnd();
    word64 size = decoder.MaxRetrievable();
    char *decodedKey = new char[size];
    decoder.Get((byte *)decodedKey, size);
    // Generate Cipher, Key, and CBC
    byte key[ AES::MAX_KEYLENGTH ], iv[ AES::BLOCKSIZE ];
    StringSource( reinterpret_cast<const char *>(decodedKey), true,
                  new HashFilter(*(new SHA256), new ArraySink(key, AES::MAX_KEYLENGTH)) );
    memset( iv, 0x00, AES::BLOCKSIZE );
    try {
        CBC_Mode<AES>::Decryption Decryptor
        ( key, sizeof(key), iv );
        StringSource( encrypted, true,
                      new HexDecoder(new StreamTransformationFilter( Decryptor,
                                     new StringSink( plain )) ) );
    }
    catch (Exception &e) { // ...
        qDebug() << "Exception while decrypting " << e.GetWhat().data();
    }
    catch (...) { // ...
    }
        qDebug() << "decrypt" << plain.data() << " " << AES::BLOCKSIZE;
    return QString::fromStdString(plain);
}

The problem is that I randomly get:

StreamTransformationFilter: invalid PKCS #7 block padding found

When decrypting the content. The encryption should fully support QString, since it may contain some Unicode data. But it doesn't work even with a basic, string which contains only [A-z][a-z][0-9]

The aesKey size is 256.

Following some answers on Stack Overflow, somebody suggested the use of HexDecoder / HexEncoder, but it does not solve the problem in my case.

frogatto
  • 28,539
  • 11
  • 83
  • 129
Veaceslav
  • 181
  • 2
  • 12
  • Based on the error (or warning?) message, it seems related to block padding, which is normally only done on the last block to make it's size == 16 bytes. – rcgldr Dec 31 '15 at 18:02
  • I always encrypt strings with a size of 256. And I think, the default_padding is applied. – Veaceslav Dec 31 '15 at 18:18
  • Wiki article for [AES](http://en.wikipedia.org/wiki/Advanced_Encryption_Standard) describes it as working with a 4 x 4 matrix of bytes, so a 16 byte block size. [PKCS #7](http://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7) padding uses the pad count for the padded byte values. – rcgldr Dec 31 '15 at 21:36
  • Please see a [working code](https://github.com/abforce/DBO-Proxy-Server/blob/Part2/Sources/CPPs/Utils/cryptoutils.cpp) in my GitHub repo. – frogatto Jan 18 '16 at 22:06

1 Answers1

0

The fist problem with my code was that I was feeding normal string in aesKey QString.

So instead of "1231fsdf$5r4" you need to give a key in hex format: [0-9][A-F]

Then, the problem was here:

char *decodedKey = new char[size];
decoder.Get((byte *)decodedKey, size);

I guess the string was full 64 bytes and there was no space for NULL at the end. The problem dissapeared after I changed to:

char *decodedKey = new char[size+2];

Now the code works fine. Hope this will help somebody in the future.

Veaceslav
  • 181
  • 2
  • 12