Java - Encryption and Decryption of an Image Using Blowfish Algorithm

 
EncryptFile.java
 
package com.java.blowfish;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;

/**
 *
 * @author dhanoopbhaskar
 */
public class EncryptFile {

    KeyGenerator keyGenerator = null;
    SecretKey secretKey = null;
    Cipher cipher = null;

    public EncryptFile() {
        try {
            /**
             * Create a Blowfish key
             */
            keyGenerator = KeyGenerator.getInstance("Blowfish");
            secretKey = keyGenerator.generateKey();

            /**
             * Create an instance of cipher mentioning the name of algorithm
             *     - Blowfish
             */
            cipher = Cipher.getInstance("Blowfish");
        } catch (NoSuchPaddingException ex) {
            System.out.println(ex);
        } catch (NoSuchAlgorithmException ex) {
            System.out.println(ex);
        }
    }

    public static void main(String[] args) {
        String fileToEncrypt = "fileToEncrypt.jpg";
        String encryptedFile = "encryptedFile.jpg";
        String decryptedFile = "decryptedFile.jpg";
        String directoryPath = "C:/Users/dhanoopbhaskar/Desktop/blowfish/";
        EncryptFile encryptFile = new EncryptFile();
        System.out.println("Starting Encryption...");
        encryptFile.encrypt(directoryPath + fileToEncrypt,
                directoryPath + encryptedFile);
        System.out.println("Encryption completed...");
        System.out.println("Starting Decryption...");
        encryptFile.decrypt(directoryPath + encryptedFile,
                directoryPath + decryptedFile);
        System.out.println("Decryption completed...");
    }

    /**
     * 
     * @param srcPath
     * @param destPath
     *
     * Encrypts the file in srcPath and creates a file in destPath
     */
    private void encrypt(String srcPath, String destPath) {
        File rawFile = new File(srcPath);
        File encryptedFile = new File(destPath);
        InputStream inStream = null;
        OutputStream outStream = null;
        try {
            /**
             * Initialize the cipher for encryption
             */
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            /**
             * Initialize input and output streams
             */
            inStream = new FileInputStream(rawFile);
            outStream = new FileOutputStream(encryptedFile);
            byte[] buffer = new byte[1024];
            int len;
            while ((len = inStream.read(buffer)) > 0) {
                outStream.write(cipher.update(buffer, 0, len));
                outStream.flush();
            }
            outStream.write(cipher.doFinal());
            inStream.close();
            outStream.close();
        } catch (IllegalBlockSizeException ex) {
            System.out.println(ex);
        } catch (BadPaddingException ex) {
            System.out.println(ex);
        } catch (InvalidKeyException ex) {
            System.out.println(ex);
        } catch (FileNotFoundException ex) {
            System.out.println(ex);
        } catch (IOException ex) {
            System.out.println(ex);
        }
    }

    /**
     * 
     * @param srcPath
     * @param destPath
     *
     * Decrypts the file in srcPath and creates a file in destPath
     */
    private void decrypt(String srcPath, String destPath) {
        File encryptedFile = new File(srcPath);
        File decryptedFile = new File(destPath);
        InputStream inStream = null;
        OutputStream outStream = null;
        try {
            /**
             * Initialize the cipher for decryption
             */
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            /**
             * Initialize input and output streams
             */
            inStream = new FileInputStream(encryptedFile);
            outStream = new FileOutputStream(decryptedFile);
            byte[] buffer = new byte[1024];
            int len;
            while ((len = inStream.read(buffer)) > 0) {
                outStream.write(cipher.update(buffer, 0, len));
                outStream.flush();
            }
            outStream.write(cipher.doFinal());
            inStream.close();
            outStream.close();
        } catch (IllegalBlockSizeException ex) {
            System.out.println(ex);
        } catch (BadPaddingException ex) {
            System.out.println(ex);
        } catch (InvalidKeyException ex) {
            System.out.println(ex);
        } catch (FileNotFoundException ex) {
            System.out.println(ex);
        } catch (IOException ex) {
            System.out.println(ex);
        }
    }
}

Output: 
Starting Encryption... 
Encryption completed... 
Starting Decryption... 
Decryption completed...


Before Encryption

After Encryption


The method doFinal() should not be used in loop or repeatedly. If we have to encrypt/decrypt multiple blocks we use update() method.
 
outStream.write(cipher.update(buffer, 0, len));

After everything is done we call doFinal() method.
 
outStream.write(cipher.doFinal());

If we use doFinal repeatedly, the encryption will work without errors. But decryption will fail throwing exception - javax.crypto.BadPaddingException

See related posts:
Java - Encryption and Decryption of an Image Using Blowfish Algorithm (using password)
Java - Encryption and Decryption of an Image Using Another Image (Blowfish Algorithm)

Post a Comment

66 Comments

  1. Hi,
    I want to encrypt file somewhere and decrypt file somewhere else.
    So, How to replace
    secretKey = keyGenerator.generateKey();
    with something like
    secretKey = getKeyObjectFromPassword("my_password");

    ReplyDelete
  2. Hi Victor,

    You can replace the following statements

    keyGenerator = KeyGenerator.getInstance("Blowfish");
    secretKey = keyGenerator.generateKey();

    with

    secretKey = new SecretKeySpec(masterPassword.getBytes(), "Blowfish");
    //import javax.crypto.spec.SecretKeySpec; should be used.

    where masterPassword is the password given.

    Regards,
    Dhanoop Bhaskar

    ReplyDelete
    Replies
    1. What exactly should be given in place of masterPassword?

      And how can I decrypt my encrypted image elsewhere using this ?

      Reply asap,
      Thank You

      Delete
    2. what is the password given?

      please specify

      Delete
    3. This version of program auto-generates a key (password). Kindly refer to
      http://www.theinsanetechie.in/2014/04/java-encryption-and-decryption-of-image.html
      for version with user defined password. You can give any alphanumeric string as password.

      Delete
  3. i am not getting encrypted image. when i open the encrypted image it opens saying invalid file format/invalid image. please help me out

    ReplyDelete
    Replies
    1. Hi Anusha,
      Before running the program you will have to modify the directory path and the file names used (in the main function). None of the applications could open an encrypted image as such; the process of encryption manipulates the file at bit-level.
      However you should be able to open the encrypted file after decryption. Please let me know if you have some other concerns.

      Regards,
      Dhanoop Bhaskar

      Delete
    2. hello ,she is saying encryption one image over another image pa.
      only one path is specfide

      Delete
  4. Hi,
    In the given program, the file "fileToEncrypt.jpg" is encrypted to get "encryptedFile.jpg". After that "encryptedFile.jpg" is decrypted and we get "decryptedFile.jpg".
    The files "fileToEncrypt.jpg" and "decryptedFile.jpg" will be identical.
    Dhanoop Bhaskar

    ReplyDelete
    Replies
    1. HI ,
      I understand coding ,but i want help, tat is encrypt "filetoEncrypt"to another image?? how to do it

      Delete
    2. Hi,
      An image on encryption would not give another image which is viewable by some application. It is literally impossible for an application to read the encrypted image file as an "image". The encoding is totally altered on encryption, so that it becomes unreadable. Decryption makes it back in a readable form.

      Regards,
      Dhanoop Bhaskar

      Delete
  5. please help bro my code is based on "AES". it encrypt everything (image ,video,ppt etc) the problem is encryption with image not encrypted

    ReplyDelete
    Replies
    1. Hi,
      Please do the following changes in the above program so that it does "AES" encryption and decryption.

      Replace

      keyGenerator = KeyGenerator.getInstance("Blowfish");

      by

      keyGenerator = KeyGenerator.getInstance("AES");

      AND

      cipher = Cipher.getInstance("Blowfish");

      by

      cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");

      Regards,
      Dhanoop Bhaskar

      Delete
  6. no that know .encryption image to another image ;
    ex : input file 1 - filetoencypt
    input file 2- images to encrypt file 1
    out put - encrypt image

    ReplyDelete
    Replies
    1. Hi Shakthi,
      Please see whether this is what you want- http://www.theinsanetechie.in/2014/04/java-encryption-and-decryption-of-image_9.html

      Delete
  7. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. Hi Ciaran,

      It is already there in the comments. A similar question was asked before, by another person.
      Instead of auto-generating the key for encryption and decryption, we can provide a password, from which the key will be derived.

      You can replace the following statements

      keyGenerator = KeyGenerator.getInstance("Blowfish");
      secretKey = keyGenerator.generateKey();

      with

      secretKey = new SecretKeySpec(masterPassword.getBytes(), "Blowfish");
      //import javax.crypto.spec.SecretKeySpec; should be used.

      where masterPassword is the password given.

      You can find the complete program here-
      http://www.theinsanetechie.in/2014/04/java-encryption-and-decryption-of-image.html

      Delete
  8. Could u plz tel me what would be the inputs for blowfish algorithm where i want to do encryption as well as decryption on watermark i;e an image .Since my project is on digital image watermarking where i m using blowfish algorithm to make my watermark (which is an image )encrypted for the security purpose so no one can make any modification to dat.

    ReplyDelete
    Replies
    1. Hi Vandana,
      The inputs to the blowfish algorithm include the image to be encrypted and the password with which the image is to be encrypted. However, the password is optional; you can auto-generate the secret key instead of deriving it from a user supplied password.

      Delete
    2. thnkz fr rply bt plz tel me dat how to convert an image in to 64 bits....since an image is in matrix form so we can take a block of an image and if i take a block then how i do the operation like XORing (bit wise).........answer me asap

      Delete
    3. Please tell me why do you need to convert an image into 64 bits. If you mean the block size, it is not needed here. The JCE (Java Cryptography Extension) abstracts such complexities from the user. We need not bother about the block size, the permutations and substitution applied, etc.

      while ((len = inStream.read(buffer)) > 0) {
      outStream.write(cipher.update(buffer, 0, len));
      outStream.flush();
      }
      outStream.write(cipher.doFinal());

      The above code snippet reads the file in multiples of 1024 bytes, (given so as to support large files without consuming much memory, you may also take all the available bytes in one read operation), encrypt (or decrypt) it - using the cipher part - and writes to another file.

      Delete
  9. Sir.. do you have the corresponding Android code??

    ReplyDelete
  10. Sir.. do you have the corresponding Android code??

    ReplyDelete
    Replies
    1. Hi Meenu,
      You can use the same code in android also :)

      Delete
    2. How can I change the code that the image uploaded by the user can be used as the input and then encrypt and decrypt?

      Delete
    3. For that you will have to implement it in a Servlet.

      Delete
  11. in this code have come this error please reply me
    Starting Encryption...
    java.io.FileNotFoundException: F:\Images\fileToEncrypt.jpg (The system cannot find the file specified)
    Encryption completed...
    Starting Decryption...
    java.io.FileNotFoundException: F:\Images\encryptedFile.jpg (The system cannot find the file specified)
    Decryption completed.




    i am put the directory right but thing is the thius code not use \ for directory to / this

    ReplyDelete
    Replies
    1. Hi Maulik,
      Hope you use windows.
      In my case the above program worked. Ideally "/" should work in Windows as well as Linux platforms.

      String fileToEncrypt = "fileToEncrypt.jpg";
      /*The image should have the name fileToEncrypt.jpg */

      Modify the statement as given below, and try re-running the program.

      String directoryPath = "F:\\Images\\";
      /* The image fileToEncrypt.jpg should be placed in path F:\Images\ */


      If you are using Linux, the statement may look like-
      String directoryPath = "/home/dhanoopbhaskar/Pictures/";
      /* where image is in the path /home/dhanoopbhaskar/Pictures/fileToEncrypt.jpg */

      Delete
  12. Repsected Sir Thanks For you reply
    i am use Window and i am change don this provided by you but the problem is not solve please help me sir

    ReplyDelete
    Replies
    1. Please share your version of the program and the image used to my email id - dhanoopbhaskar@gmail.com

      Delete
  13. i am getting "javax.crypto.IllegalBlockSizeException: last block incomplete in decryption" while decrypting image back

    ReplyDelete
    Replies
    1. Replace

      cipher = Cipher.getInstance("Blowfish");

      by

      cipher = Cipher.getInstance("Blowfish/ECB/PKCS5Padding");

      Delete
  14. C:\SujanaPrograms>java EncryptFile
    Exception in thread "main" java.lang.NoClassDefFoundError: EncryptFile (wrong na
    me: com/java/blowfish/EncryptFile)
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(Unknown Source)
    at java.security.SecureClassLoader.defineClass(Unknown Source)
    at java.net.URLClassLoader.defineClass(Unknown Source)
    at java.net.URLClassLoader.access$100(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)

    I am getting this error while execution of code..what I have to do for this?

    ReplyDelete
    Replies
    1. Hi Sujana Pathuri,

      "javac EncryptFile.java" will compile the program without fail.
      However, inorder to run it, the class file (EncryptFile.class) should be present in the file path mentioned in the package directive in the program.
      i.e., "EncryptFile.class" should be placed in com/java/blowfish/

      After that run the program as "java com/java/blowfish/EncryptFile"

      Delete
  15. Is there a code to encrypt a folder??

    ReplyDelete
    Replies
    1. Hi,

      The Java Cryptography Extension (JCE) does not provide a way to do it, as such. You can do it recursively encrypting the files and sub folders in it or by taking a zip of the folder and encrypting. JCE provides facility to encrypt only file(s).

      Delete
  16. sir i want image encryption and decryption using username nd password using ...????

    ReplyDelete
    Replies
    1. Hi,
      All that you can do is to implement your own method OR just concatenate username and password and use as the "password" to encrypt the decrypt the image.

      Delete
  17. Hello, When i use this code, the encryption works perfectly but my problem is when its decrypting it gives me this error :
    javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher

    How can i fix this error ? Thank you

    ReplyDelete
    Replies
    1. Replace

      cipher = Cipher.getInstance("Blowfish");

      by

      cipher = Cipher.getInstance("Blowfish/ECB/PKCS5Padding");

      Delete
  18. Hi Dhaoop,

    Do you have any experience with hiding data inside the encrypted video stream ?

    ReplyDelete
  19. hi
    please give me code for encryption and decryption digital image using color signal

    ReplyDelete
    Replies
    1. Hi,
      Sorry, I'm not the right person to help you out. Consult someone from electronics background.

      Thanks.

      Delete
  20. sir if i want to do it with RSA algorithm,so what changes should i make in your program?

    ReplyDelete
    Replies
    1. Hi,
      We cannot encrypt data of size greater than the key length using RSA algorithm in java (JCE). (However we can use our own implementation of the RSA algorithm)

      If needed, you can use RSA to encrypt the password and use the encrypted password further to encrypt the image using DES, AES, Blowfish or any such symmetric crypto systems.

      Delete
  21. Sir,

    I Siddaram shetty,I've gone through ur blog(theinsanetechie.in), Iam doing my project based on RSA algorithm , I used this algorithm for encryption(using public key) and decryption(using private key) of an image.I need to show encryption at one system and decryption at other system, is this possible, if yes, What is the procedure?


    Once I encrypted the image, when I tried to open the encrypted image, the message Iam getting was invalid image, the image ur trying to open is corrupt or damaged etc..Why Iam getting these messages? Pls clarify my doubt? Thanks in advance

    ReplyDelete
    Replies
    1. Hi,
      Already explained in one of the previous comments.

      Thanks.

      Delete
  22. how can i get secret key from this program

    ReplyDelete
    Replies
    1. The 'SecretKey' may not be in human readable format. If you want to reuse in a separate program you can serialize the object to a file and reuse.
      (Read about serialization and the interface java.io.Serializable)

      Delete
  23. how can i get secret key from this program

    ReplyDelete
  24. I am getting the exception java.io.FileNotFoundException... I have replaced the directory path as you mentioned in one of the above comments.... But still getting the same error.. Please do reply

    ReplyDelete
  25. Code is getting compiled. But its showing FileNotFoundException when I run it. I have tried the methods you mentioned earlier but of no use. I am using windows 8. Suggest me the solution.

    ReplyDelete
    Replies
    1. While executing the program EncryptFile.class should be in the directory com/java/blowfish.

      While execution you should change directory (cd) to parent of com and run

      #java com.java.blowfish.EncryptFile


      (The java interpreter will seek for com/java/blowfish/EncryptFile.class)

      Delete
  26. Hi, I splitted my Program as encrypt and Decryt file.

    encryption part is Working but Decryption part is Showing error message as

    non-static method(java.lang.String, java.lang.String,)

    ReplyDelete
    Replies
    1. It seems that you placed the code for decryption some where outside the main method.
      Either make the method (where code for decryption is placed) as 'static' or invoke it using the object of the class from the main method
      (We can not invoke a non-static method from a static method in Java - main() is static)

      Delete
  27. umm hey can you tell me how to encode or decode user selected images?

    ReplyDelete
    Replies
    1. Hi,
      Instead of hard coding the file paths, make use of command line arguments to take user supplied file paths in to the program.

      Delete
  28. i am not getting encrypted image. when i open the encrypted image i get a cross sign,but i can see the decrypted image same as that of the input image.

    ReplyDelete
  29. i am not getting encrypted image. when i open the encrypted image it shows a cross symbol but i can see the decrypted image.

    ReplyDelete
    Replies
    1. Please try to understand what 'encryption' and 'decryption' is before going in to the code. Thanks.

      Delete
  30. Good article, but there is Logical "Bhanda" :D like if user comes uploads some file and logs out, new keys are generated and so on, he comes back and tries to retrieve then he will never get file decrypted due to re initialization of all keys. Better approach to do it more realistic way like from user input file upload and download. :)

    ReplyDelete
    Replies
    1. This program is just to demonstrate the use of JCE. Another program which takes user-defined password is also there as a separate post (mentioned in this post itself). Thanks for your feedback.

      Delete
  31. heelo bro i run program i get encrpt image and sencond time i will run only decrypt method error shows javax.crypto.BadPaddingException: Given final block not properly padded help me

    ReplyDelete
    Replies
    1. Hi,
      This program auto-generates the key (password) for encryption/decryption. It will be different for each execution of the program. That's why the error. Kindly use another version of the program which takes user-defined password (mentioned in this post itself).

      Delete
  32. Thanks a lot... It helped a lot.

    ReplyDelete