Вопрос по aes, encryption, java, image – Шифрование и дешифрование файла изображения

0

В сочетании с моим другимвопроси после изменения этой маленькой части кодов

FileOutputStream output = new FileOutputStream("sheepTest.png");
    CipherOutputStream cos = new CipherOutputStream(output, pbeCipher);
    ImageIO.write(input, "PNG", cos);
    cos.close();

из расшифрованной части я столкнулся с другой ошибкой,

Exception in thread "main" java.lang.IllegalArgumentException: image == null!
at javax.imageio.ImageTypeSpecifier.createFromRenderedImage(Unknown Source)
at javax.imageio.ImageIO.getWriter(Unknown Source)
at javax.imageio.ImageIO.write(Unknown Source)
at encypt.com.trial.main(trial.java:82)

и когда я нажимаю на sheepTest.png, файл пуст. Где ошибка (ы)? Может кто-нибудь помочь мне решить ошибку? Спасибо.

public class trial {
public static void main(String[] arg) throws Exception {

   // Scanner to read the user's password. The Java cryptography
   // architecture points out that strong passwords in strings is a
   // bad idea, but we'll let it go for this assignment.
   Scanner scanner = new Scanner(System.in);
   // Arbitrary salt data, used to make guessing attacks against the
   // password more difficult to pull off.
   byte[] salt = { (byte) 0xc7, (byte) 0x73, (byte) 0x21, (byte) 0x8c,
           (byte) 0x7e, (byte) 0xc8, (byte) 0xee, (byte) 0x99 };

   {
     File inputFile = new File("sheep.png");
      BufferedImage input = ImageIO.read(inputFile);
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
      SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
     // Get a password from the user.
     System.out.print("Password: ");
     System.out.flush();
     PBEKeySpec pbeKeySpec = new PBEKeySpec(scanner.nextLine().toCharArray());          
     // Set up other parameters to be used by the password-based
     // encryption.
     PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, 20);
     SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
     // Make a PBE Cyhper object and initialize it to encrypt using
     // the given password.
     Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
     pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);
     FileOutputStream output = new FileOutputStream("sheepTest.png");
     CipherOutputStream cos = new CipherOutputStream(
            output, pbeCipher);
       //File outputFile = new File("image.png");
         ImageIO.write(input,"PNG",cos);
      cos.close();          

   }
   // Now, create a Cipher object to decrypt for us. We are repeating
   // some of the same code here to illustrate how java applications on
   // two different hosts could set up compatible encryption/decryption
   // mechanisms.
  {
       File inputFile = new File("sheepTest.png");
         BufferedImage input = ImageIO.read(inputFile);
       // Get another (hopefully the same) password from the user.
      System.out.print("Decryption Password: ");
       System.out.flush();
       PBEKeySpec pbeKeySpec = new PBEKeySpec(scanner.next().toCharArray());
       // Set up other parameters to be used by the password-based
       // encryption.
       PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, 20);
       SecretKeyFactory keyFac = SecretKeyFactory
               .getInstance("PBEWithMD5AndDES");
       SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
       // Make a PBE Cyper object and initialize it to decrypt using
       // the given password.
       Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
       pbeCipher.init(Cipher.DECRYPT_MODE, pbeKey, pbeParamSpec);
       // Decrypt the ciphertext and then print it out.
       /*byte[] cleartext = pbeCipher.doFinal(ciphertext);
       System.out.println(new String(cleartext));*/
       FileOutputStream output = new FileOutputStream("sheepTest.png");
       CipherOutputStream cos = new CipherOutputStream(
              output, pbeCipher);
        ImageIO.write(input,"PNG",  cos);
        cos.close();

   }
   }
}
Это не имеет смысла. У вас есть ImageIO.write () - & gt; CipherOutputStream - & gt; FileOutputStream, но вы пытаетесь использовать CipherInputStream & lt; - ImageIO.read () & lt; - FileInputStream. user207421
@ Твистер, можете ли вы сказать мне, что этот метод лучше всего подходит для двух или более изображений? user3233280
Я уже решаю. :) Twister

Ваш Ответ

2   ответа
4

BufferedImage input = ImageIO.read(inputFile);

Документация дляImageIO.read говорит:

& quot; Если ни один зарегистрированный ImageReader не утверждает, что может прочитать результирующий поток, возвращается значение null. & quot;

Этот ноль передается на этот вызов, что приводит к NPE:

ImageIO.write(input,"PNG",  cos);

Я не знаком с этим API, но из документации и того, что я вижу здесь, я могу понять, что причинаImageIO.read возвращает ноль, потому что он пытается интерпретировать данные изображения в файле, но не может, потому что он зашифрован. Вам необходимо сначала расшифровать данные, прежде чем вы сможете интерпретировать их как изображение.

Вы выполняете дешифрование, но при преобразовании формата используется исходный зашифрованный файл, а не дешифрованные данные изображения.

+1 за нахождение источника проблемы;)
MadProgrammer был достаточно хорош, чтобы написать пример для вас.
Есть ли примеры кодов после того, как вы это объясните? Смути здесь. Twister
@Nate Случайно, знаете ли вы, как случайным образом зашифровать изображение вместо жесткого кодирования файла изображения, а затем зашифровать / расшифровать его? Twister
Если у вас есть другой вопрос, задайте его как отдельный вопрос, чтобы на него можно было правильно ответить. (Но вам нужно будет объяснить это более подробно, чем это, если вы хотите получить хороший ответ.)
5

хорошо), я изменил ваш раздел дешифрования

// Note that we are not reading the image in here...
System.out.print("Decryption Password: ");
System.out.flush();
PBEKeySpec pbeKeySpec = new PBEKeySpec(scanner.next().toCharArray());
// Set up other parameters to be used by the password-based
// encryption.
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, 20);
SecretKeyFactory keyFac = SecretKeyFactory
        .getInstance("PBEWithMD5AndDES");
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
// Make a PBE Cyper object and initialize it to decrypt using
// the given password.
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
pbeCipher.init(Cipher.DECRYPT_MODE, pbeKey, pbeParamSpec);

// We're now going to read the image in, using the cipher
// input stream, which wraps a file input stream
File inputFile = new File("sheepTest.png");
FileInputStream fis = new FileInputStream(inputFile);
CipherInputStream cis = new CipherInputStream(fis, pbeCipher);
// We then use all that to read the image
BufferedImage input = ImageIO.read(cis);
cis.close();

// We then write the dcrypted image out...
// Decrypt the ciphertext and then print it out.
FileOutputStream output = new FileOutputStream("sheepTest.png");
ImageIO.write(input, "PNG", output);

Мой пример основан на выводах NateCK. Если вы сочтете это полезным, было бы неплохо, но NateCK заслуживает похвалы;)

@ Твистер Я обновил код, чтобы использовать «право» имена файлов: P
@ Твистер, да, извините, вы должны переименовать картинки, я использовал мои изображения ввода / вывода для проверки кода, извините
После запуска целых кодов, я полагаю, сколько всего фотографий? Twister
@ Твистер У вас должно получиться два, оригинал и (наконец) расшифрованный. Я использовал три для моего тестирования
Ой. Оно работает. Но одна вещь, которую я запутываю, это фотографии PNG. Картинка, которую я храню в своем проекте, это sheep.png (зашифрованная часть), которая будет находиться под этимFile inputFile = new File("sheep.png"); , а затем следует вывод наFileOutputStream output = new FileOutputStream("sheepTest.png");, Затем для расшифровки частьFile inputFile = new File("C:/hold/encrypt.png");, я должен использовать изображение барана или ..? Twister

Похожие вопросы