Шифрование строк работает, шифрование типа массива byte[] не работает

#java #security #encryption #aes-gcm

#java #массивы #шифрование #aes

Вопрос:

Я использую следующую ССЫЛКУ для шифрования и попробовал это со строками, и это сработало. Однако, поскольку я имею дело с изображениями, мне нужно, чтобы процесс шифрования / дешифрования выполнялся с байтовыми массивами. Поэтому я изменил код в этой ссылке на следующий:

 public class AESencrp {

    private static final String ALGO = "AES";
    private static final byte[] keyValue = 
    new byte[] { 'T', 'h', 'e', 'B', 'e', 's', 't',
'S', 'e', 'c', 'r','e', 't', 'K', 'e', 'y' };

    public static byte[] encrypt(byte[] Data) throws Exception {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.ENCRYPT_MODE, key);
        byte[] encVal = c.doFinal(Data);
        //String encryptedValue = new BASE64Encoder().encode(encVal);
        return encVal;
    }

    public static byte[] decrypt(byte[] encryptedData) throws Exception {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.DECRYPT_MODE, key);

        byte[] decValue = c.doFinal(encryptedData);
        return decValue;
    }

    private static Key generateKey() throws Exception {
        Key key = new SecretKeySpec(keyValue, ALGO);
        return key;
    }
  

и класс проверки является:

 public class Checker {

    public static void main(String[] args) throws Exception {

        byte[] array = new byte[]{127,-128,0};
        byte[] arrayEnc = AESencrp.encrypt(array);
        byte[] arrayDec = AESencrp.decrypt(arrayEnc);

        System.out.println("Plain Text : "   array);
        System.out.println("Encrypted Text : "   arrayEnc);
        System.out.println("Decrypted Text : "   arrayDec);
    }
}
  

Однако мой вывод:

 Plain Text : [B@1b10d42
Encrypted Text : [B@dd87b2
Decrypted Text : [B@1f7d134
  

Таким образом, расшифрованный текст не совпадает с обычным текстом. Что мне следует сделать, чтобы исправить это, зная, что я попробовал пример в исходной ссылке, и он работал со строками?

Комментарии:

1. На самом деле вы не знаете, правильный ли расшифрованный вывод или нет — вы печатаете адреса объектов, а не содержимое. Сравните содержимое массивов.

Ответ №1:

То, что вы видите, является результатом метода toString() массива. Это не содержимое массива byte. Используйте java.util.Arrays.toString(array) для отображения содержимого массивов.

[B это тип (массив байтов), а 1b10d42 это хэш-код массива.

Комментарии:

1. Спасибо 🙂 это сработало. Я приму ваше. У меня все еще есть один вопрос, как вы думаете, я могу запустить этот код на Android без каких-либо проблем? И если я преобразую изображения в массив байтов, затем зашифрую, получу, расшифрую и снова преобразоваю в изображение, возникнут ли какие-либо проблемы?

2. Я никогда ничего не делал на Android, но если API поддерживается, я не понимаю, почему это не сработает. Если изображения большие, избегайте загрузки всего массива байтов в память для его шифрования. Прочитайте его фрагментами и отправьте фрагменты в CipherOutputStream.

3. Что я могу сделать, если я не знаю файл изображения, которое я собираюсь получить? Похоже, я сталкиваюсь с той же ошибкой, потому что я устанавливаю размер массива байтов вручную, например, byte[] array = new byte [60000], где полученное изображение должно составлять около 60 кб.

4. Вам не нужно инициализировать какой-либо массив байтов, поскольку метод шифрования doFinal делает это за вас и возвращает расшифрованный массив байтов.

Ответ №2:

Однако мой вывод:

 Plain Text : [B@1b10d42
Encrypted Text : [B@dd87b2
Decrypted Text : [B@1f7d134
  

Это потому, что вы распечатываете результат вызова toString() для массива байтов. Это не покажет вам ничего полезного, кроме указания идентификатора ссылки.

Вы должны либо просто сравнить данные открытого текста с расшифрованными данными байт за байтом (что вы можете сделать с Arrays.equals(byte[], byte[]) ), либо, если вы действительно хотите отобразить содержимое, распечатать представление hex или base64. [Arrays.toString(byte[])][2] даст вам представление, но hex, вероятно, будет легче читать. В сторонних библиотеках существует множество классов шестнадцатеричного форматирования, или вы могли бы найти метод в Stack Overflow.

Комментарии:

1. спасибо, Джон, да, вы абсолютно правы, не могли бы вы, пожалуйста, помочь мне с вопросом, который я опубликовал выше?

2. @Adroidist: Неясно, что вы подразумеваете под «если я не знаю файл изображения» — это не имеет смысла. Если вы говорите о размере , вы должны в основном рассматривать его как поток — продолжайте читать блок, шифровать его, читать следующий блок и т.д., Пока у вас не закончатся данные. То же самое для расшифровки.

Ответ №3:

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

Класс проверки:

 public class Checker {

    public static void main(String[] args) throws Exception {

        byte[] array = "going to encrypt".getBytes();
        byte[] arrayEnc = AESencrp.encrypt(array);
        byte[] arrayDec = AESencrp.decrypt(arrayEnc);

        System.out.println("Plain Text : "   array);
        System.out.println("Encrypted Text : "   arrayEnc);
        System.out.println("Decrypted Text : "   new String(arrayDec));
    }
}