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