2014-01-10 4 views
4

У меня большая проблема с криптографией AES между Java и C++ (для конкретного CryptoPP), что я ожидал, что это будет проще, чем асимметричная криптография, которую мне удалось решить ранее.Java AES CBC Decryption First Block

Когда я дешифрую 48 байт, а результатом является массив byte [] из 38 байт (размер + код + hashOfCode), последние 22 байта дешифруются правильно, а первые 16 ошибочны.

try { 
     cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC"); 
     byte[] key = { 107, -39, 87, -65, -1, -28, -85, -94, 105, 76, -94, 
       110, 48, 116, -115, 86 }; 
     byte[] vector = { -94, 112, -23, 93, -112, -58, 18, 78, 1, 69, -92, 
       102, 33, -96, -94, 59 }; 
     SecretKey aesKey = new SecretKeySpec(key, "AES"); 
     byte[] message = { 32, -26, -72, 25, 63, 114, -58, -5, 4, 90, 54, 
       88, -28, 3, -72, 25, -54, -60, 17, -53, -27, -91, 34, -101, 
       -93, -3, -47, 47, -12, -35, -118, -122, -77, -7, -9, -123, 
       7, -66, 10, -93, -29, 4, -60, -102, 16, -57, -118, 94 }; 

     IvParameterSpec aesVector = new IvParameterSpec(vector); 
     cipher.init(Cipher.DECRYPT_MODE, aesKey, aesVector); 
     byte[] wynik = cipher.doFinal(message); 
     Log.d("Solution here", "Solution"); 
     for (byte i : wynik) 
      Log.d("Solution", "" + i); 
    } catch (Exception e) { 
     Log.d("ERROR", "TU"); 
     e.printStackTrace(); 
    } 

Decrypted сообщение, что я ожидал получить это:

0 0 0 32 10 0 16 43 81 -71 118 90 86 -93 -24 -103 -9 -49 14 -29 -114 82 81 -7 -59 3 -77 87 -77 48 -92 -111 -125 -21 123 21 86 4 

Но то, что я получаю

28 127 -111 92 -75 26 18 103 79 13 -51 -60 -60 -44 18 126 -9 49 14 -29 -114 82 81 -7 -59 3 -77 87 -77 48 -92 -111 -125 -21 123 21 86 4 

Как вы можете видеть только последние 22 байта являются одна и та же.

Я знаю, что AES работает с блоками, и поэтому я думал, что, возможно, что-то с вектором инициализации неверно (потому что только первый блок сломан), но, как вы можете видеть, я устанавливаю вектор так, как я думаю ОК.

И я понятия не имею, почему это работает именно так. Любая помощь будет действительно оценена, потому что у меня заканчивается время.

[EDIT] Я добавляю инициализацию шифрования. Как вы писали, это AES/CBC/PKCS5Padding.

На стороне CryptoPP/C++ (то есть на самом деле не мой код, так что я бы обеспечить наименьшую часть информации, которую я могу найти полезным) есть:

CryptoPP::CBC_Mode< CryptoPP::AES>::Encryption m_aesEncryption; 
CryptoPP::CBC_Mode< CryptoPP::AES>::Decryption m_aesDecryption; 

QByteArray AESAlgorithmCBCMode::encrypt(const QByteArray& plain) 
{ 
std::string encrypted; 

try { 
    StringSource(reinterpret_cast<const byte*>(plain.data()), plain.length(), true, 
      new StreamTransformationFilter(m_aesEncryption, 
        new StringSink(encrypted))); 

} catch (const CryptoPP::Exception& e) { 
    throw SymmetricAlgorithmException(e.what()); 
} 

return QByteArray(encrypted.c_str(), encrypted.length()); 

}

QByteArray AESAlgorithmCBCMode::decrypt(const QByteArray& encrypted) 
{ 
std::string plain; 
try { 
    StringSource(reinterpret_cast<const byte*>(encrypted.data()), encrypted.length(), true, 
      new StreamTransformationFilter(m_aesDecryption, 
        new StringSink(plain))); 
} catch (const CryptoPP::Exception& e) { 
    throw SymmetricAlgorithmException(e.what()); 
} 

return QByteArray(plain.c_str(), plain.length()); 

}

Ключ и вектор инициализации точно такие же (я проверил). Увлекательная часть - это часть более крупного коммуникационного протокола, и предыдущее сообщение было зашифровано и дешифровано отлично. И были и нули в начале.

+0

Я думаю, вы также должны добавить к сообщению: 1. Как вы устанавливаете шифр, например Cipher.getInstance («AES/CBC/PKCS5Padding») 2. C + + версия вашего кода. – user1516873

+0

И первые три нуля вашего ожидаемого результата выглядят очень подозрительно – user1516873

+0

Если первые 16 байт в конечном итоге повреждены, вероятно, вы используете неправильный вектор инициализации. Убедитесь, что они совпадают. Я также хотел бы указать, что при шифровании сообщения всегда следует генерировать случайный IV - использование статической IV-утечки информации об открытом тексте, как это делает режим ECB. – ntoskrnl

ответ

0

Ответ был задан в вопросе; который не изменился даже после четкого комментария, что он должен быть опубликован в качестве ответа.

Это говорит ответ:

Дело в том, что каждый раз, когда doFinal() вызывается, он сбрасывает состояние шифра. Что вам нужно сделать, это сохранить последний блок сообщения (зашифрованный для Decryptor и дешифрованный для Encryptor), который будет использоваться в следующий раз как новый InitializationVector. Затем следует вызвать init() с этим новым IV. Естественно, должны быть предоставлены различные экземпляры Cipher для шифрования и дешифрования.