Crypto lib AES CBC problem with decryption
-
Hi, I have the following code which I refered from https://www.cryptopp.com/wiki/Advanced_Encryption_Standard
I need to either encrypt or decrypt so I modified the code a little.
Ignore variable txt.#include "modes.h" #include "aes.h" #include "filters.h" #include "osrng.h" #include "randpool.h" #include "hex.h" #include <QDebug> #include <QString> #define encr 1 #define decr 0 #define AUTH "1111222233334444" // for testing only #define IVKY "4444333322221111" // for testing only using namespace CryptoPP; using namespace std; QString crypt(QString txt,QString auth,QString ivk,bool e) { SecByteBlock key(AES::DEFAULT_KEYLENGTH); byte iv[ AES::BLOCKSIZE ]; memcpy(key,auth.toStdString().c_str(),CryptoPP::AES::DEFAULT_KEYLENGTH); memcpy(iv, ivk.toStdString().c_str(),CryptoPP::AES::BLOCKSIZE); string plain = "Hello"; string cipher, encoded, recovered; QByteArray qb; /*********************************\ * ENCRYPTION \*********************************/ //if(e) { try { cout << "plain text: " << plain << endl; CBC_Mode< AES >::Encryption e; e.SetKeyWithIV( key, key.size(), iv ); // The StreamTransformationFilter adds padding // as required. ECB and CBC Mode must be padded // to the block size of the cipher. StringSource ss( plain, true, new StreamTransformationFilter( e, new StringSink( cipher ) ) // StreamTransformationFilter ); // StringSource qDebug() << "orig cipher" << cipher.c_str(); QByteArray cip = cipher.c_str(); //QString cip = cipher.c_str(); qb = cip.toBase64(); qDebug() << "cipher to base64" << qb; QString qq = QByteArray::fromBase64(qb); //QByteArray qq = QByteArray::fromBase64(qb); qDebug() << "cipher from base64" << qq; } catch( const CryptoPP::Exception& e ) { cerr << e.what() << endl; exit(1); } } /*********************************\ * DECRYPT \*********************************/ //else { try { CBC_Mode< AES >::Decryption d; d.SetKeyWithIV( key, key.size(), iv ); // The StreamTransformationFilter removes // padding as required. StringSource ss( cipher, true, new StreamTransformationFilter( d, new StringSink( recovered ) ) // StreamTransformationFilter ); // StringSource cout << "recovered text: " << recovered << endl; } catch( const CryptoPP::Exception& e ) { cerr << e.what() << endl; exit(1); } } if(e) { return qb; } else { return recovered.data(); } } MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); // decrypt QString text = "Text_to_decrypt"; QString d = crypt(text,AUTH,IVKY,decr); qDebug() << d; }
Output window:
My requirement is to encrypt user credentials in a JSON file. From the output window I cannot use original cipher, so I converted it into Base64 to check. Looked like I can use it since it is mostly alphanumeric. But when I convert it from Base64 again the output was halfway correct and later different as you see in the image. It also differs if the type of assigment variable is QString/QByteArray. What is going wrong here? I want to make use of this Base64 or any other format that has no special characters after encryption. Please suggest. Also when I pass Base64 format as input to "txt" (that is generated from Hello->cipher->Base64) and convert it to (from Base64->std::string) to decrypt function, it produces "invalid cipher size."
Any help is appreciated.
-
at dark-o-clock and not reading your post carefully, consider this. base64 requires a fixed block size. I think you must pad your input string to the length it expects for input and output. I also believe that AES/CBC is a block cypher so correct padding is important there too.
-
@gmk27 said in Crypto lib AES CBC problem with decryption:
What is going wrong here?
The output of the AES cipher will be a binary blob of data (a multiple of 16 bytes) that may contain zero bytes. Zero bytes terminate strings, and other non-printables have effects when sent to a terminal. So, you cannot rely on any binary goodness being output in a useful way to the terminal.
A zero byte in the cipher text will also terminate the construction of the QByteArray cip. From there, qb will potentially be incomplete, qq will contain the incomplete cip mangled in some way to become a QString (as your code is posted). Trying to AES decrypt a partial cipher block will not go well.
When handling binary data, it is best to stay in the bunch-of-bytes world. Check output by dumping it in hex or base64.
My requirement is to encrypt user credentials in a JSON file
Do you need to be able to decrypt those credentials? If not, and it is generally not necessary if you are later using them to authenticate a user, then you should consider a salted one-way hash function. QCryptographicHash provides such hash functions, and QRandomGenerator can provide the salt value.
-
Thank you both for the info.
I realized I just over complicated my approach that had thrown me into confusion.
I did a lot of string conversions that simply is an overkill.
Now it is working with some modifications in the code above. I will try to update it in later time.