-1

i want to create a very simple encrypt/decrypt project. but at first i want to read jpg file and write it to a file with a given password then read that file again and check the password in the file and the provided password but i get:

Exception in thread "main" java.lang.IllegalArgumentException: im == null!
    at javax.imageio.ImageIO.write(Unknown Source)
    at javax.imageio.ImageIO.write(Unknown Source)
    at GSM.AES.deccryption(AES.java:105)
    at GSM.AES.main(AES.java:27)

My codes:

public static void main(String args[]) 
        {
            myWrite();
            String encryptedFilePath = System.getProperty("user.dir")+ "\\"+"Encrypted"+".mmlooloo";
            String destinationFilePath = System.getProperty("user.dir") + "\\";
            try {
                myRead(encryptedFilePath,destinationFilePath,"123456");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return;
        }

My encrypt :

 public static void myWrite() {

            try {

                System.out.println("Plesase Enter Number Of Pages !!!!!");
                BufferedReader bufferRead = new BufferedReader(new InputStreamReader(System.in));
                int numberOfPage = Integer.valueOf(bufferRead.readLine().toString());

                String dirName=  System.getProperty("user.dir")+"\\";


                byte[] base64StringEnc;
                ByteArrayOutputStream baos=new ByteArrayOutputStream(1000);
                FileOutputStream  myMatLabFileEnc = null;

                String filePath = System.getProperty("user.dir")+ "\\"+"Encrypted"+".mmlooloo";
                myMatLabFileEnc = new FileOutputStream (filePath);
                String imagFileName;
                String imgPathString;
                String password = "123456";
                myMatLabFileEnc.write(password.getBytes());
                myMatLabFileEnc.write("\n".getBytes());

               for(int i = 1 ; i<=numberOfPage ;i++)
               {    

                     imagFileName = Integer.toString(i) +".jpg";         
                     BufferedImage img=ImageIO.read(new File(dirName,imagFileName));
                     ImageIO.write(img, "jpg", baos);
                     baos.flush();

                     myMatLabFileEnc.write(baos.toByteArray());
                     myMatLabFileEnc.write("\n".getBytes());

                     baos.reset();
                     imgPathString = dirName + imagFileName;
                     File  f = new File(imgPathString);
                     f.delete();

               }
                     myMatLabFileEnc.close();
                     baos.close();
                     return;

                } catch (FileNotFoundException ex) {
                    System.out.println(ex.toString());
            }catch(IOException ex){
                System.out.println(ex.toString());
            }
        }

and my decrypt:

public static int myRead(String encryptedfilePath,String encryptedFileDir,String inputPassword) throws FileNotFoundException, IOException{

            FileReader encryptedFile=new FileReader(encryptedfilePath);
            BufferedReader reader = new BufferedReader(encryptedFile);
            String encryptedImag;
            String encryptedSavesdPassword = reader.readLine();
            byte []encryptedInputPassword = inputPassword.getBytes();
            byte []temp = encryptedSavesdPassword.getBytes();
            if(!Arrays.equals(temp,encryptedInputPassword)){
                return -1;
            }
            int i = 1;

            while((encryptedImag = reader.readLine()) != null){

                byte[] bytearray = encryptedImag.getBytes();
                BufferedImage imagRecover=ImageIO.read(new ByteArrayInputStream(bytearray));
                String outputRecoverdFileName = Integer.toString(i)+"_recoverd.jpg";
                ImageIO.write(imagRecover, "jpg", new File(encryptedFileDir,outputRecoverdFileName));
                ++i;
            }

            return 1;

        }

and AES.java:105 is:

ImageIO.write(imagRecover, "jpg", new File(encryptedFileDir,outputRecoverdFileName));

i checked imagRecover is null but i do not know why? i think you can try it just name your image files like 1.jpg, 2.jpg and so on ...

Harald K
  • 26,314
  • 7
  • 65
  • 111
mmlooloo
  • 18,937
  • 5
  • 45
  • 64
  • You're writing binnary data. You cannot assure there's not an end of line in the binnary of an image. Probably there are lot's of carre returns and end of lines inside that stuff... Each of the linea you're expecting to be fully conatructed images make the imageio.read fail and return null as stated in the javadoc for that method. I sugest you to base64 encode each image before writing and treat thw file as a text file with a printwriter. Otherwise you should try kind-of a WAD file like thoae in good'ol doom, saving the poaition and length of each file. – eduyayo Sep 04 '14 at 22:06
  • Btw... Have u read about java.util.zip?? – eduyayo Sep 04 '14 at 22:07
  • @eduyayo thanks it works but why do i lose quality? for example my original image is 551kB but my recover is 181KB. i used Baase64 encode decode method to write and read. – mmlooloo Sep 05 '14 at 02:36
  • @mmlooloo When using `ImageIO.write(...)` you are using default parameters for compression/quality. If these don't match the settings your input file already had, you will end up with a smaller/larger file. – Harald K Sep 05 '14 at 11:57
  • @haraldK thank you if you can tell me what to do, that i do not lose any quality i will accept your answer. – mmlooloo Sep 05 '14 at 13:14
  • @eduyayo if you post your first comment as an answer i will vote it up. – mmlooloo Sep 05 '14 at 13:25
  • @mmlooloo Use a lossless format, like PNG or TIFF. Or better yet, don't decode/encode the image in the first place. Just copy the bytes. – Harald K Sep 05 '14 at 13:31
  • @haraldK actually i want to encrypt it in server side and then download it in my android app and decrypt it (i do not want to use HTTPS because i want to store it as an encrypted file in a SD card) can you suggest me any algorithm to encrypt images. i know you are knowledgeable in this field.Thank you. – mmlooloo Sep 05 '14 at 13:51
  • See "answer" below... – Harald K Sep 05 '14 at 14:04

1 Answers1

2

Disclaimer: This is not the complete answer, but it's too long for a comment.

This is what I meant by the comment:

don't decode/encode the image in the first place. Just copy the bytes.

Using this code, you will not recompress the JPEG, and thus not lose quality.

Instead of the following code:

imagFileName = Integer.toString(i) +".jpg";         
BufferedImage img=ImageIO.read(new File(dirName,imagFileName));
ImageIO.write(img, "jpg", baos);
baos.flush();

Just copy the bytes from the file to baos like this:

imagFileName = Integer.toString(i) +".jpg";         
InputStream input = new FileInputStream(new File(dirName, imagFileName));
try {
    copy(input, baos);
}
finally {
    input.close();
}

Copy method:

public void copy(InputStream input, OutputStream output) throws IOException {
    byte[] buffer = new byte[1024];
    int len;

    while ((len = input.read(buffer, 0, buffer.length)) >= 0) {
        output.write(buffer, 0, len);
    }
}

Likewise, in the decrypt part, replace:

byte[] bytearray = encryptedImag.getBytes();
BufferedImage imagRecover=ImageIO.read(new ByteArrayInputStream(bytearray));
String outputRecoverdFileName = Integer.toString(i)+"_recoverd.jpg";
ImageIO.write(imagRecover, "jpg", new File(encryptedFileDir,outputRecoverdFileName));

With:

byte[] bytearray = encryptedImag.getBytes();
InputStream input = new ByteArrayInputStream(bytearray));
String outputRecoverdFileName = Integer.toString(i) + "_recoverd.jpg";
OutputStream output = new FileOutputStream(new File(encryptedFileDir, outputRecoverdFileName)));
try {
    copy(input, output);
}
finally {
    output.close();
}
Harald K
  • 26,314
  • 7
  • 65
  • 111
  • Thank you very much now i think i can implement any encryption algorithm to baos am i right ?!!! – mmlooloo Sep 05 '14 at 14:09
  • As long as you can reproduce the same bytes after decryption, you should be good to go. :-) – Harald K Sep 05 '14 at 14:12
  • 1
    Fine, especially about not using `String` for `byte[]`. Java is special in that String is Unicode capable of combining all scripts in a text. Hence there always is a conversion to binary data (in the encoding given, or defaulting to the operating system's). That conversion does not work lossless on pure binary data. – Joop Eggen Sep 05 '14 at 14:13