2015-12-31 2 views
3

У меня есть следующий код, который шифрует и расшифровывает сообщение.AES-шифрование на QStrings, libcrypto ++

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

Проблема заключается в том, что я случайно получить:

StreamTransformationFilter: invalid PKCS #7 block padding found 

Когда дешифрования контента. Шифрование должно полностью поддерживать QString, , так как оно может содержать некоторые данные Unicode. Но это не работает, даже с базовым, строку, которая содержит только [Az] [AZ] [0-9]

aesKey размер 256.

После некоторых ответов на переполнение стека, кто-то предложил использование HexDecoder/HexEncoder, но это не решит проблему в моем случае.

+0

Исходя из сообщения об ошибке (или предупреждения?), Похоже, связано с заполнением блока, которое обычно выполняется только в последнем блоке, чтобы сделать его размером == 16 байт. – rcgldr

+0

Я всегда шифрую строки размером 256. И я думаю, применяется default_padding. – Veaceslav

+0

Статья Wiki для [AES] (http://en.wikipedia.org/wiki/Advanced_Encryption_Standard) описывает ее как работу с 4 x 4 матрицей байтов, поэтому размер блока по 16 байтов. [PKCS # 7] (http://en.wikipedia.org/wiki/Padding_ (криптография) # PKCS7) padding использует счетчик пэдов для добавленных байтовых значений. – rcgldr

ответ

0

Проблема с моим кодом заключалась в том, что я кормил обычную строку в aesKey QString.

Таким образом, вместо "1231fsdf $ 5r4" Вы должны дать ключ в шестнадцатеричном формате: [0-9] [AF]

Тогда задача здесь:

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

Я думаю, строка была заполнена 64 байтами, и в конце не было места для NULL. Проблема исчезла после того, как я изменился на:

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

Теперь код работает нормально. Надеюсь, это поможет кому-то в будущем.

Смежные вопросы