Расшифруйте AES с неверным размером IV - PullRequest
1 голос
/ 15 октября 2019

У меня есть файл, зашифрованный в AES 128 CBC (с openssl в cpp). Шифрование выполнено с неверным размером iv (8 вместо 16). Это факт, это неправильно, и я ничего не могу с этим поделать. Файл, который я получаю, выглядит следующим образом:
[8 бит IV] [Зашифрованные данные]

Мне нужно прочитать этот файл с помощью Java (android), но я не могу получить правильный результат.

Вот то, что я использую для расшифровки файла:

public String decrypt(byte[] key, byte[] datasencrypted) {
        // Split IV and actual Datas into 2  differents buffers
        int dataSize = datasencrypted.length - 8; // 8 = wrong iv size
        byte[] encrypted = new byte[dataSize];
        byte[] ivBuff = new byte[8];
        System.arraycopy(datasencrypted,0,ivBuff,0,8);
        System.arraycopy(datasencrypted,8,encrypted,0,dataSize);

        try {
            IvParameterSpec iv = new IvParameterSpec(ivBuff);
            SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] original = cipher.doFinal(encrypted);

            return new String(original);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }

Очевидно, этот код генерирует исключение InvalidAlgorithmParameterException: ожидаемая длина IV - 16. Если я изменю размер буфера iv на 16, не болееисключение, но конечный результат - просто бред.

Кроме того, ключ определен как unsigned char [] в CPP, поэтому, чтобы преобразовать его в byte [] в Java, я просто приведу значения следующим образом:

mKey =  new byte[]{(byte)0x8c,(byte)0x96,0x5f,.....}};
  • Можно ли расшифровать этот файл в java (он работает на стороне cpp)?
  • Как узнать, какой тип заполнения использовать?
  • приведение значения ключа может быть проблемой?

--- РЕДАКТИРОВАТЬ --- Как предлагается здесь, это код CPP, который может расшифровать файл:. AES_KEYLEN = 128.
AES_ROUND = 5.

size_t Helper::DecryptAES(unsigned char* encMsg, size_t encMsgLen, unsigned char** decMsg)
{
    size_t decLen = 0;
    size_t blockLen = 0;

    *decMsg = (unsigned char*)malloc(encMsgLen);
    if (*decMsg == nullptr) return 0;

    if (!EVP_DecryptUpdate(mAESDecryptCtx, (unsigned char*)*decMsg, (int*)&blockLen, encMsg, (int)encMsgLen)) {
        return 0;
    }
    decLen += blockLen;

    if (!EVP_DecryptFinal_ex(mAESDecryptCtx, (unsigned char*)*decMsg + decLen, (int*)&blockLen)) {
        return 0;
    }
    decLen += blockLen;

    return decLen;
}

bool Helper::InitAES(unsigned char* key, unsigned char* salt)
{
    mAESEncryptCtx = static_cast<EVP_CIPHER_CTX*>(malloc(sizeof(EVP_CIPHER_CTX)));
    mAESDecryptCtx = static_cast<EVP_CIPHER_CTX*>(malloc(sizeof(EVP_CIPHER_CTX)));

    mAESKey = static_cast<unsigned char*>(malloc(AES_KEYLEN / 8));
    mAESIv = static_cast<unsigned char*>(malloc(AES_KEYLEN / 8));

    int size = EVP_BytesToKey(EVP_aes_128_cbc(), EVP_sha256(), salt, key, AES_KEYLEN / 8, AES_ROUNDS, mAESKey, mAESIv);

    if (size != AES_KEYLEN / 8)
    {
        return false;
    }

    EVP_CIPHER_CTX_init(mAESEncryptCtx);
    if (!EVP_EncryptInit_ex(mAESEncryptCtx, EVP_aes_128_cbc(), nullptr, mAESKey, mAESIv))
        return false;

    EVP_CIPHER_CTX_init(mAESDecryptCtx);
    if (!EVP_DecryptInit_ex(mAESDecryptCtx, EVP_aes_128_cbc(), nullptr, mAESKey, mAESIv))
        return false;

    return true;
}

Здесь IvSIze в порядке, но когда iv добавляется в файл, читается только 8 бит вместо 16.

1 Ответ

3 голосов
/ 15 октября 2019

И ключ, и IV получены через EVP_BytesToKey, так что я думаю, что перед шифротекстом находится соль , а не IV. Это, однако, в коде, который вы не показали.

Если вы хотите реализовать в основном проприетарную EVP_BytesToKey, тогда доступно несколько реализаций Java . Обратите внимание, что вам придется выполнить разделение между ключом и IV самостоятельно (по 16 байт).

Примечания:

  • CBC требует IV в 16 байтов, выполнить его невозможноCBC с IV из 8 байтов (реализация может попытаться заполнить недостающие байты самостоятельно или, конечно, использовать данные за пределами буфера в C);
  • C ++ действительно мешает, размер IVнапример, не должно зависеть от размера ключа;
  • пока вы его используете, пожалуйста, сделайте описание протокола, а не ставьте следующего разработчика в то же положение, в котором вы находитесь сейчас;
  • все это использует старую технологию, плохой механизм получения ключа, шифрование CBC без аутентификации, я бы обновил ваш протокол.
...