0

In conjunction from my another question, and after changing this small part of the codes

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

from the decrypt part, I've faced another error which is this

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)

and when i click the sheepTest.png, the file is empty. Where is the mistake(s)? Can anyone help me to solve the error? Thank you.

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();

   }
   }
}
Community
  • 1
  • 1
Twister
  • 199
  • 3
  • 9
  • 19
  • This doesn't make sense. You have ImageIO.write() -> CipherOutputStream -> FileOutputStream, but you are attempting CipherInputStream <- ImageIO.read() <- FileInputStream. – user207421 Aug 27 '12 at 06:55
  • @Twister can u pls tell me is this method speed is best for two or more than two images – user3233280 Dec 22 '14 at 18:59

2 Answers2

6

Further to NateCK's insightful post (well done by the way), I've modified your decrypt section

// 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);

My example is based on NateCKs findings. If you find it useful, an upvote would be nice, but NateCK deserves the credit ;)

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Oh. It works. But one thing im confuse is the png pictures. The picture that i store inside my project is sheep.png(encrypt part) which will be under this `File inputFile = new File("sheep.png");` , then followed by it will output to a `FileOutputStream output = new FileOutputStream("sheepTest.png");`. Then for the decrypt part, the `File inputFile = new File("C:/hold/encrypt.png");`, i should use the picture of sheepTest or..? – Twister Aug 27 '12 at 06:02
  • After running the whole codes, Im suppose to have how many pictures in total? – Twister Aug 27 '12 at 06:03
  • @Twister yeah, sorry, you should rename the pictures, I was using my input/output images to test the code, sorry – MadProgrammer Aug 27 '12 at 06:04
  • @Twister I've updated the code to use the "right" file names :P – MadProgrammer Aug 27 '12 at 06:06
  • @Twister You should end up with two, the original and (finally) the decrypted. I used three for my testing – MadProgrammer Aug 27 '12 at 06:06
  • Ohh. So the decrypted image will be actually encrypted but after going through the decrypt image it will show the same image as the original one, instead the only thing change is the bytes of the image is it? – Twister Aug 27 '12 at 06:09
  • @Twister No, what you started with (in the way of files) is fine. I just send the image to an intermediate step while I was getting my head around you code ;). You should have `sheep.png` and `sheepTest.png`, which, when you run the program, should look the same ;) – MadProgrammer Aug 27 '12 at 06:09
  • @Twister let me see if I can clarify this ;). You have 1 input file (`sheep.png`), which is encrypted and saved to `sheepTest.png`. This file (`sheepTest.png`) is then decrypted and saved back to `sheepTest.png`...there clear as mud ;) – MadProgrammer Aug 27 '12 at 06:14
  • Is not the size of the picture became large? :\ Hmm. I seee – Twister Aug 27 '12 at 06:14
  • The size may change, it's difficult to tell and a lot will come down to the internal writer algorithm. Don't stress of this to much. If the two images "look" the same, this is more important. PNG is a compressed image format – MadProgrammer Aug 27 '12 at 06:15
  • When i remove the decrypt part of the codes and just run the encrypt part, the sheepTest.png when i open why it says the picture appears to be damaged , corrupted or the size too large ? – Twister Aug 27 '12 at 06:16
  • Ahh~ I see. As long as after decrypting, the image appears to be the same then is alright already right..? New to this encryption so have to ask clearly. Haha – Twister Aug 27 '12 at 06:17
  • @Twister 1. Yes, don't worry about the final decrypted size of the image, it may change 2. If you're trying to read encrypt file that you've succeeded in your task, the file should be unreadable ;) – MadProgrammer Aug 27 '12 at 06:19
  • Oh. By any chance, do you know how to randomly encrypt a image instead of hardcoding a image file and then encrypt/decrypt it? – Twister Aug 27 '12 at 06:28
  • Not of the top of my head, no – MadProgrammer Aug 27 '12 at 06:29
4

I'd guess that this line is returning null:

BufferedImage input = ImageIO.read(inputFile);

The documentation for ImageIO.read says:

"If no registered ImageReader claims to be able to read the resulting stream, null is returned."

That null is passed on to this call, which results in the NPE:

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

I'm not familiar with this API, but from the documentation and what I see here, I think I can infer that the reason ImageIO.read is returning null is because it's trying to interpret the image data in the file, but it can't because it's encrypted. You need to decrypt the data first before you can interpret it as an image.

You are doing the decryption, but your format conversion is using the original, encrypted file as its input, not the decrypted image data.

Nate C-K
  • 5,744
  • 2
  • 29
  • 45
  • Is there a example codes after you explain this? Confuse here. – Twister Aug 27 '12 at 05:48
  • @Nate By any chance, do you know how to randomly encrypt a image instead of hardcoding a image file and then encrypt/decrypt it? – Twister Aug 27 '12 at 06:28
  • If you have another question, ask it as a separate question so it can be answered properly. (But you will need to explain it more extensively than that if you want a good answer.) – Nate C-K Aug 27 '12 at 13:00
  • I will say, though, that you might want to search for "circular buffer". – Nate C-K Aug 27 '12 at 13:24