tags:

views:

65

answers:

2

Hello, I want to make program that encrypts (later decrypts) user inputted string. Here is beginning for encryption:

QString getData = ui->text->toPlainText(); //Data to process
std::string output; //Result will be Base32 encoded string, so std::string is fine.

Now, I have to convert QString to char* or std::string so it can be accepted with Crypto++. I thought that QByteArray would be fine, as it has .data() function, which returns char *. (getData always 17 or more bytes long: CryptoPP requires at least 17 bytes for AES encryption). So, I have used following code:

QByteArray data;
data.append(getData);

//Creating key and iv:

//Creating AES encryptor:

//Encrypting AES and Base32:
CryptoPP::StringSource((const byte*)data.data(), data.size() , true,
    new CryptoPP::StreamTransformationFilter( Encryptor,
        new CryptoPP::Base32Encoder(
                new CryptoPP::StringSink(output)
        ) // Base32Encoder
    ) // StreamTransformationFilter
); // StringSource

ui->text->clear();
getData = output.c_str();
ui->text->setText(getData);

Everything is seems to be fine. But I want it to support non-ASCII characters (I mean russian, lithuanian etc.). After decryption they change to ?. How could I fix this? I understand, that std::string doesn`t support them.


EDIT: Here is updated code:

Encryption:

QString getData = ui->text->toPlainText(); //Data to process
std::string output;

QByteArray data = getData.toUtf8();

//Creating key and iv: <..>

//Creating AES encryptor: <..>

//Encrypting AES and Base32:
CryptoPP::StringSource((const byte*) data.data(),getData.size()*2, true,
    new CryptoPP::StreamTransformationFilter( Encryptor,
        new CryptoPP::Base32Encoder(
                new CryptoPP::StringSink(output)
        ) // Base32Encoder
    ) // StreamTransformationFilter
); // StringSource

ui->text->clear();
getData = output.c_str();
ui->text->setText(getData);

And decryption:

QString getData = ui->text->toPlainText();
QByteArray data;
data.append(getData);
std::string output;

//Creating key and iv:
byte key[ CryptoPP::AES::DEFAULT_KEYLENGTH ],
      iv[ CryptoPP::AES::BLOCKSIZE ];

//Memsetting them: (randomization needed)
::memset( key, 0x01, CryptoPP::AES::DEFAULT_KEYLENGTH );
::memset(  iv, 0x01, CryptoPP::AES::BLOCKSIZE );

//Creating AES decryptor:
CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption
    Decryptor( key, sizeof(key), iv );

//Decrypting Base32 and AES
CryptoPP::StringSource((const byte*) data.data(), data.size(), true,
    new CryptoPP::Base32Decoder(
        new CryptoPP::StreamTransformationFilter( Decryptor,
            new CryptoPP::StringSink(output)
        ) // StreamTransformationFilter
    ) // Base32Encoder
); // StringSource

ui->text->clear();
getData = QString::fromUtf8(output.c_str());
ui->text->setText(getData);

Does it have any bugs I have missed?

+1  A: 

Use reinterpret_cast<byte*>(QString::data()) instead. Don't try to actually do code page conversion here -- AES does not care. Use an ArraySink instead of a StringSink.

Keep in mind that the size of the actual QString::data() buffer is twice the number of characters contained there, because it uses UTF-16.

Billy ONeal
`ArraySink` requires `byte*` array and length. So `byte*` array should be `QByteArray` and length is `getData.size()*2` (getData`s length from encryption keeping in mind that "buffer is twice the number of characters contained there") that I should pass to decryption function?
EdgeLuxe
@EdgeLuxe: No -- your conversion to QByteArray is actually what's causing the destruction of the international characters. QString exposes it's buffer -- why convert to another immediate type? `byte` is used by CryptoPP because AES can encrypt any stream of bytes. It doesn't care about the actual contents of those bytes.
Billy ONeal
`//Encrypting AES and Base32:``QChar * datatoproc = getData.data();``CryptoPP::StringSource(reinterpret_cast<byte*>(datatoproc),getData.size()*2, true,`` new CryptoPP::StreamTransformationFilter( Encryptor,`` new CryptoPP::Base32Encoder(`` new CryptoPP::StringSink(output)`` ) // Base32Encoder`` ) // StreamTransformationFilter`` ); // StringSource`Oh, I don`t get it. Encryption function is correct?
EdgeLuxe
Edited the question.
EdgeLuxe
+2  A: 

I think you're losing data when converting from QString to QByteArray. Try this:

QByteArray data = getData.toUtf8();

...

getData = QString::fromUtf8( output.c_str() );
Tom Sirgedas
I guess UTF-8 is not enough. UTF-16 or UTF-32 maybe?
EdgeLuxe
What do you mean by "not enough"? From wikipedia: "Like UTF-16 and UTF-32, UTF-8 can represent every character in the Unicode character set"
Tom Sirgedas
@EdgeLuxe: Keep in mind that in UTF-8, the length of the string is NOT equal to the byte length of the string.
Billy ONeal
Edited the question.
EdgeLuxe