Не могу расшифровать AES

236
26 ноября 2017, 14:26

Мой коллега шифрует данные с помощью AES-256 без вектора используя модуль node.js aes-js. Соотвественно ключ у него представляет из себя 32 размерный массив, а шифрованная строка - строка.

В Java Android я пытаюсь сделать что-то вроде того

 public static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
    SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.DECRYPT_MODE, skeySpec);
    byte[] decrypted = cipher.doFinal(encrypted);
    return decrypted;
}

Но мне всегда выдает ошибка -

javax.crypto.IllegalBlockSizeException: last block incomplete in decryption

А вот в TextView я загоняю таким способом

  byte[] key = new byte[]{83, 63, (byte) 180, (byte) 178, (byte) 169, 38, 21, 10, 62, (byte) 160, (byte) 216, (byte) 191, 122, 13, 55, 68, (byte) 181, 4, (byte) 180, 20, 8, 117, (byte) 138, 36, 51, 26, 7, 90, 3, (byte) 184, 47, 17};
    TextView t = findViewById(R.id.text);
    try {
        t.setText(Decrypt.decrypt(key, "cc1e55b3a5c6fbcc22c67bcafbb2e2704e25c9db8959f4a9d6570666d73fb15c49139b".getBytes()).toString());
    } catch (GeneralSecurityException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }

Вот так шифрует и дешифрует коллега у себя

let encrypt = function(text, key){    
if(!key){
    key = KEY;
}
let encryptionBlock = new aes.ModeOfOperation.ctr(key, new aes.Counter(100));
return aes.utils.hex.fromBytes(encryptionBlock.encrypt(aes.utils.utf8.toBytes(text)))
}

И дешифрование

let decrypt = function(text, key){    
if(!key){
    key = KEY;
}
let encryptionBlock = new aes.ModeOfOperation.ctr(key, new aes.Counter(100));
return aes.utils.utf8.fromBytes(encryptionBlock.decrypt(aes.utils.hex.toBytes(text)))
}

Как мне расшифровать этот текст? Уже множество способов перепробовал. Заранее спасибо

Answer 1

Как минимум 2 вещи вы делаете неправильно:

  1. "...".getBytes(). Зашифрованные данные - это бинарные данные, а не строка. Вы должны получить байты из hex строки, а не байты из символов.
  2. Даже если вы первое сделаете верно, у вас длина зашифрованного сообщения - 35 байт. В AES она должна быть кратна размеру блока, то есть 16 байтам. Поэтому джава кидает исключение.

Я не знаю, каким образом было получено ваше зашифрованное сообщение, но оно точно не получено стандартным применением AES. Поэтому я не могу подсказать, как его расшифровать.

После обновления вопроса.

В случае с CTR нужно делать так:

byte[] ciphertext = new byte[] { 113, (byte)202, 74, (byte)141, 19 };
byte[] key = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
byte[] counter = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100 };
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
IvParameterSpec ctrParameter = new IvParameterSpec(counter);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, ctrParameter);
byte[] plain = cipher.doFinal(ciphertext);
System.out.println(new String(plain, StandardCharsets.UTF_8));

Выводит hello. Обратите внимание на массив counter. Последний байт 100, что соответствует счетчику заданному в nodejs коде.

Еще могу добавить, что изпользование одного и того же счетчика с одним и тем же ключом очень большая дыра в безопасности, злоумышленник сможет расшифровать сообщение даже не зная ключа.

Answer 2

Попробуйте так:

public static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
    final byte[] bt = new byte[16];
    Arrays.fill(bt, (byte)0); 
    SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
    Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
    cipher.init(Cipher.DECRYPT_MODE, skeySpec, bt);
    return cipher.doFinal(encrypted);
}
READ ALSO
Программное отключение экрана android

Программное отключение экрана android

Пытаюсь программно отключить экран использую функцию:

154
Отображение игроков на сервере

Отображение игроков на сервере

Здравствуйте! Создаю сервер на Java, он как бы есть, но как на нем вместе играть? Есть игра, просто мир, в котором должны играть по сети и видеть...

174
как можно взять текст из динамически заполненного элемента listview

как можно взять текст из динамически заполненного элемента listview

Мне нужно поочередно зашифровать каждый элемент списка ListViewДля этого я с помощью цикла for хочу взять текст из элемента, зашифровать его и вернуть...

140
Распределенные задания по расписанию

Распределенные задания по расписанию

Есть два сервера с WildFly и одна БД

157