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
{
objFileInputStream = new FileInputStream(strFileName);
objFileOutputStream = new FileOutputStream(strFileName + "." + strExtension);
PBEKeySpec objPBEKeySpec = new PBEKeySpec(strPassword.toCharArray());
SecretKeyFactory objSecretKeyFactory = SecretKeyFactory.getInstance(strMessageDigestAlgorithm);
SecretKey objSecretKey = objSecretKeyFactory.generateSecret(objPBEKeySpec);
byte[] byteSalt = new byte[8];
Random objRandom = new Random();
objRandom.nextBytes(byteSalt);
int intIteration = intPasswordHashIteration;
PBEParameterSpec objPBEParameterSpec = new PBEParameterSpec(byteSalt, intIteration);
Cipher objCipher = Cipher.getInstance("PBEWithMD5AndDES");
objCipher.init(Cipher.ENCRYPT_MODE, objSecretKey, objPBEParameterSpec);
objFileOutputStream.write(byteSalt);
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
{
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(strMessageDigestAlgorithm);
SecretKey objSecretKey = objSecretKeyFactory.generateSecret(objPBEKeySpec);
byte[] byteSalt = new byte[8];
objFileInputStream.read(byteSalt);
int intIteration = intPasswordHashIteration;
PBEParameterSpec objPBEParameterSpec = new PBEParameterSpec(byteSalt, intIteration);
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.