Click here to Skip to main content
Click here to Skip to main content

CryptBox

By , 17 Feb 2013
Rate this:
Please Sign up or sign in to vote.

Introduction

File Encryption and Decryption using Password Based Encryption (PBE).

Password-Based Encryption (PBE) derives an encryption key from a password. In order to make the task of getting from password to key very time-consuming for an attacker, most PBE implementations (as the one shown below) will mix in a random number, known as a salt, to create the key.

PBE algorithm supported in j2se1.4 (Other algorithms are supported in later versions of the SunJCE and other providers)

There are times when we want to effectively select the encryption key. We might want to encrypt a file based on a passphrase entered by us, so that we can remember it. In this case, we want the only secret information to be the passphrase.

The technique of generating a secret key from a user-generated passphrase is usually called password-based encryption (PBE). As you might imagine, it is loaded with difficulty. In particular:

  • Our requirement and the security requirement usually conflict: we require an easy-to-remember passphrase, or at least one that's made of recognisable characters and short enough to write down; yet for secure encryption by today's standards, we require at least 128 strongly random bits (and ideally more);
  • password-based encryption is typically used in applications where an attacker can repeatedly try to guess the password undetected and beyond the control of the genuine sender/recipient (if the password is being used to log into the server, it can be detect that so many invalid attempts were made and in the worst case shut down the server to prevent further attempts; but if an eavesdropper takes a copy of the encrypted ZIP file we use, we'll never know that they're sitting there with a 100,000-processor botnet trying to brute-force the password, and they can essentially sit doing it for as long as they like).   

PBE (Password Based Encryption) = hashing + symmetric encryption

A 64 bit random number (the salt) is added to the password and hashed using a Message Digest Algorithm (e.g. MD5).
Number of times the password is hashed is determined by the iteration count.  Adding a random number and hashing multiple times enlarges the key space.

Be carefull while setting the password or hash iteration count to encrypt file

If password or hash iteration count is lost, then there may not be any possibility to retrieve any of it.
This will lead to unsuccessful decryption of encrypted file and hence encrypted file may not be used forever.

Background

I wanted to protect my files from others to open it. That is when I thought of encrypting my files and store it in hard drive. Even if someone wanted to open it, s/he have to decrypt the file and then can open it. Since I encrypt the file using a password and also a password hash iteration is added, it is difficult for anybody to decrypt it.

I got the working idea from http://cs.saddleback.edu/rwatkins/CS4B/Crypto/FileEncryptor.html and full credit goes to it for encryption and decryption.

Screenshot

  • Files can be added in CryptBox to encrypt or decrypt in two ways.
    • Either click Select button. Selecting Encrypt radio button will help user to select any files to encrypt. Selecting Decrypt radio button will help user to select any encrypted files with extension "enc".
    • Drag and Drop files from Windows Explorer by selecting one or multiple files. CryptBox will either Encrypt or Decrypt depending what radio button is selected.
  • Selected files will be shown under File(s) column with full path.
  • Status will be set as "In Queue" which will change as per the process status when Encryption or Decryption starts.
  • Sub Status column will display the intermediate work which is in progress. 
  • Once user have selected files, click on Start button. A pop up window will open.
  • The CryptBox uses PBEWithMD5AndDES for Message Digest Algorithm.
  • Enter Password Hash Iteration which is by default 100. Number of times the password is hashed is determined by the iteration count.
  • Enter the password to protect the file and will be used for cryptography.
  • Re Password should be exactly same as Password to check whether it is same password you want.
  • While decrypting an encrypted file, user require same Message Digest Algorithm, Hash Iteration and Password which was used to encrypt that file.

  • At the time of Encrypting or Decrypting files, user can Detail button to check the details status of operation. It also shows status progress bar of % of completion.

 

  • If user provides wrong Message Digest Algorithm, Password Hash Iteration or Password at the time of Decrypting files which does not matches with Encrypted file, then CryptBox will ask to re enter these details, so that it can be decrypted successfully.
  • At the time of Encryption whatever Message Digest Algorithm, Password Hash Iteration or Password has been provided for a file should be same for that file at the time of Decryption.

Using the code

Encryption method

public int EncryptFile(String strFileName, String strMessageDigestAlgorithm, int intPasswordHashIteration, String strPassword, String strExtension) throws Exception
{
    FileInputStream objFileInputStream;
    FileOutputStream objFileOutputStream;

    try
    {
        // File to encrypt.  It does not have to be a text file!
        // Password must be at least 8 characters (bytes) long
        objFileInputStream = new FileInputStream(strFileName);
        objFileOutputStream = new FileOutputStream(strFileName + "." + strExtension);

        // Use PBEKeySpec to create a key based on a password.
        // The password is passed as a character array
        PBEKeySpec objPBEKeySpec = new PBEKeySpec(strPassword.toCharArray());
        //SecretKeyFactory objSecretKeyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
        SecretKeyFactory objSecretKeyFactory = SecretKeyFactory.getInstance(strMessageDigestAlgorithm);
        SecretKey objSecretKey = objSecretKeyFactory.generateSecret(objPBEKeySpec);

        // PBE = hashing + symmetric encryption.  A 64 bit random
        // number (the salt) is added to the password and hashed
        // using a Message Digest Algorithm (MD5 in this example.).
        // The number of times the password is hashed is determined
        // by the interation count.  Adding a random number and
        // hashing multiple times enlarges the key space.
        byte[] byteSalt = new byte[8];
        Random objRandom = new Random();
        objRandom.nextBytes(byteSalt);
        //int intIteration = 100;
        int intIteration = intPasswordHashIteration;

        //Create the parameter spec for this salt and interation count
        PBEParameterSpec objPBEParameterSpec = new PBEParameterSpec(byteSalt, intIteration);

        // Create the cipher and initialize it for encryption.
        Cipher objCipher = Cipher.getInstance("PBEWithMD5AndDES");
        objCipher.init(Cipher.ENCRYPT_MODE, objSecretKey, objPBEParameterSpec);

        // Need to write the salt to the (encrypted) file.  The
        // salt is needed when reconstructing the key for decryption.
        objFileOutputStream.write(byteSalt);

        // Read the file and encrypt its bytes.
        byte[] byteInput = new byte[64];
        int intRead;
        while ((intRead = objFileInputStream.read(byteInput)) != -1)
        {
            byte[] byteOutput = objCipher.update(byteInput, 0, intRead);
            if (byteOutput != null)
            {
                objFileOutputStream.write(byteOutput);
            }
        }

        byte[] byteOutput = objCipher.doFinal();
        if (byteOutput != null)
        {
            objFileOutputStream.write(byteOutput);
        }

        objFileInputStream.close();
        objFileOutputStream.flush();
        objFileOutputStream.close();

        return 0;
    }
    catch(Exception ex)
    {
        JOptionPane.showMessageDialog(null, ex, "CryptBox Error", JOptionPane.ERROR_MESSAGE);

        return 1;
    }
} 

Decryption method

public int DecryptFile(String strFileName, String strMessageDigestAlgorithm, int intPasswordHashIteration, String strPassword, String strExtension) throws Exception
{
    FileInputStream objFileInputStream;
    FileOutputStream objFileOutputStream;

    try
    {
        // File to decrypt.
        // Password must be at least 8 characters (bytes) long
        objFileInputStream = new FileInputStream(strFileName);
        objFileOutputStream = new FileOutputStream(strFileName.substring(0, strFileName.length() - strExtension.length() - 1));

        PBEKeySpec objPBEKeySpec = new PBEKeySpec(strPassword.toCharArray());
        //SecretKeyFactory objSecretKeyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
        SecretKeyFactory objSecretKeyFactory = SecretKeyFactory.getInstance(strMessageDigestAlgorithm);
        SecretKey objSecretKey = objSecretKeyFactory.generateSecret(objPBEKeySpec);

        // Read in the previouly stored salt and set the iteration count.
        byte[] byteSalt = new byte[8];
        objFileInputStream.read(byteSalt);
        //int intIteration = 100;
        int intIteration = intPasswordHashIteration;

        PBEParameterSpec objPBEParameterSpec = new PBEParameterSpec(byteSalt, intIteration);

        // Create the cipher and initialize it for decryption.
        Cipher objCipher = Cipher.getInstance("PBEWithMD5AndDES");
        objCipher.init(Cipher.DECRYPT_MODE, objSecretKey, objPBEParameterSpec);

        byte[] byteInput = new byte[64];
        int intRead;
        while ((intRead = objFileInputStream.read(byteInput)) != -1)
        {
            byte[] byteOutput = objCipher.update(byteInput, 0, intRead);
            if (byteOutput != null)
            {
                objFileOutputStream.write(byteOutput);
            }
        }

        byte[] byteOutput = objCipher.doFinal();
        if (byteOutput != null)
        {
            objFileOutputStream.write(byteOutput);
        }

        objFileInputStream.close();
        objFileOutputStream.flush();
        objFileOutputStream.close();

        return 0;
    }
    catch(Exception ex)
    {
        JOptionPane.showMessageDialog(null, ex, "CryptBox Error", JOptionPane.ERROR_MESSAGE);

        return 1;
    }
}
  • These 2 (i.e Encryption and Decryption) are the main methods in CryptBox. There is another method which delete previous files after encryption or decryption.
  • Encryption or Decryption takes time depending on file size. E.g. if it is 1 GB file, it takes approx. 8 min to encrypt or decrypt file.
  • CryptBox has been implemented with SwingWorker which is an abstract class. SwingWorker is designed for situations where it need to have a long running task run in a background thread and provide updates to the UI either when done, or while processing. 

Points of Interest 

If user enters wrong details to decrypt an encrypted file, it will never do so untill and unless correct information is provided.

History

This is the first version and submitted on 18-Feb-2013.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)

About the Author

Biswas, Sumit
Tester / Quality Assurance
India India
I am a Performance Engineer, but I like programming. i don't do it as a specialty, but because i love it. anyone who supports source code sharing on the same plane as me.
Anyone who wants to learn more about me can feel free to contact me. Meanwhile, i'd appreciate your feedback. Get in touch sumitsushil@gmail.com
 
* If this article is helpful, please give reputation points.
* Don't forget to tip the waiter with your appreciation.

Comments and Discussions

 
QuestionNice Work PinprofessionalSonuKSingh17-Oct-13 3:05 
QuestionMy vote of 3 Pinmemberjcurl25-Feb-13 10:17 
GeneralMy vote of 5 Pingroupevan89719-Feb-13 1:30 
GeneralMy vote of 3 PinmemberDeepankar Ranjan Dey18-Feb-13 3:15 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140415.2 | Last Updated 18 Feb 2013
Article Copyright 2013 by Biswas, Sumit
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid