Wednesday, December 7, 2011

Simple Cryptography example in Java

The Java security APIs span a wide range of areas, including cryptography, public key infrastructure, secure communication, authentication, and access control. Java security technology provides the developer with a comprehensive security framework for writing applications, and also provides the user or administrator with a set of tools to securely manage applications.
Source : http://www.oracle.com/technetwork/java/javase/tech/index-jsp-136007.html

javax.crypto.Cipher
This class provides the functionality of a cryptographic cipher for encryption and decryption. It forms the core of the Java Cryptographic Extension (JCE) framework.
Cipher API : http://docs.oracle.com/javase/6/docs/api/javax/crypto/Cipher.html

Cipher: initialized with keys, these used for encrypting/decrypting data. There are various types of algorithms: symmetric bulk encryption (e.g. AES, DES, DESede, Blowfish, IDEA)
http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html

Blowfish 
Blowfish has a 64-bit block size and a variable key length from 1 bit up to 448 bits
Blowfish Wiki : http://en.wikipedia.org/wiki/Blowfish_%28cipher%29

To run this example you will need below mentioned JAR files in classpath.
jce.jar
rt.jar


If you are using JDK 6 or higher version, These JAR files are implicitly present. You can cross verify in JRE folder. Probably in "C:\Program Files\Java\jre6\lib"

Hence C:\Program Files\Java\jre6\lib\jce.jar and C:\Program Files\Java\jre6\lib\rt.jar are implicitly set in your classpath.

Below is the sample self explanatory Java program using Blowfish Cipher. Directly you can run the program and see output.

Simple Blowfish Cipher Example in java

/* SimpleCryptography.java */

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class SimpleCryptography {
    
    private String AlgoName = "Blowfish";
    
    private String keyString = "DesireSecretKey";
    
    public String encrypt(String sValue) throws Exception {
        
        SecretKeySpec skeySpec = new SecretKeySpec(keyString.getBytes(), AlgoName);
        Cipher cipher = Cipher.getInstance(AlgoName);
        
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        
        byte[] encrypted = cipher.doFinal(sValue.getBytes());
        
        BASE64Encoder bASE64Encoder = new BASE64Encoder();
        String enStr = bASE64Encoder.encodeBuffer(encrypted);    
        
        return enStr;
    }
    
    public String decrypt(String sValue) throws Exception {
        
        SecretKeySpec skeySpec = new SecretKeySpec(keyString.getBytes(), AlgoName);
        Cipher cipher = Cipher.getInstance(AlgoName);
        
        BASE64Decoder bASE64Decoder = new BASE64Decoder();
        byte decrytByt[] = bASE64Decoder.decodeBuffer(sValue);
        
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        
        byte decrypted[] = cipher.doFinal(decrytByt);
        
        String deStr = new String(decrypted).trim();
        
        return deStr;
    }
    
    public static void main(String[] args) throws Exception {
        
        SimpleCryptography obj = new SimpleCryptography();
        
        String password = "MadanChaudhary";
        
        System.out.println("password : "+password);
        
        String encrypted_password = obj.encrypt(password);
        
        System.out.println("encrypted_password : "+encrypted_password);
        
        String decrypted_password = obj.decrypt(encrypted_password);
        
        System.out.println("decrypted_password : "+decrypted_password);

    }
}

Output :

password : MadanChaudhary
encrypted_password : 0LpwIuI0V+44sbZ5w3CCZw==

decrypted_password : MadanChaudhary

Below are the known Errors and exceptions I observed while writing this program.

1.
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
    at com.sun.crypto.provider.BlowfishCipher.engineDoFinal(DashoA13*..)
    at javax.crypto.Cipher.doFinal(DashoA13*..)
Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
    at com.sun.crypto.provider.BlowfishCipher.engineDoFinal(DashoA13*..)
    at javax.crypto.Cipher.doFinal(DashoA13*..)

2.
java.security.InvalidKeyException: Illegal key size or default parameters
    at javax.crypto.Cipher.a(DashoA13*..)
    at javax.crypto.Cipher.a(DashoA13*..)
    at javax.crypto.Cipher.a(DashoA13*..)
    at javax.crypto.Cipher.init(DashoA13*..)
    at javax.crypto.Cipher.init(DashoA13*..)
Exception in thread "main" java.security.InvalidKeyException: Illegal key size or default parameters
    at javax.crypto.Cipher.a(DashoA13*..)
    at javax.crypto.Cipher.a(DashoA13*..)
    at javax.crypto.Cipher.a(DashoA13*..)
    at javax.crypto.Cipher.init(DashoA13*..)
    at javax.crypto.Cipher.init(DashoA13*..)

3.
java.security.NoSuchAlgorithmException: Cannot find any provider supporting MyAlgo
    at javax.crypto.Cipher.getInstance(DashoA13*..)
Exception in thread "main" java.security.NoSuchAlgorithmException: Cannot find any provider supporting MyAlgo
    at javax.crypto.Cipher.getInstance(DashoA13*..)

4.
java.security.InvalidKeyException: Invalid key length: 16 bytes
    at com.sun.crypto.provider.DESCipher.engineGetKeySize(DashoA13*..)
    at javax.crypto.Cipher.b(DashoA13*..)
    at javax.crypto.Cipher.a(DashoA13*..)
    at javax.crypto.Cipher.a(DashoA13*..)
    at javax.crypto.Cipher.a(DashoA13*..)
    at javax.crypto.Cipher.init(DashoA13*..)
    at javax.crypto.Cipher.init(DashoA13*..)
Exception in thread "main" java.security.InvalidKeyException: Invalid key length: 16 bytes
    at com.sun.crypto.provider.DESCipher.engineGetKeySize(DashoA13*..)
    at javax.crypto.Cipher.b(DashoA13*..)
    at javax.crypto.Cipher.a(DashoA13*..)
    at javax.crypto.Cipher.a(DashoA13*..)
    at javax.crypto.Cipher.a(DashoA13*..)
    at javax.crypto.Cipher.init(DashoA13*..)
    at javax.crypto.Cipher.init(DashoA13*..)

5.
java.security.NoSuchAlgorithmException: Cannot find any provider supporting DSA
    at javax.crypto.Cipher.getInstance(DashoA13*..)
Exception in thread "main" java.security.NoSuchAlgorithmException: Cannot find any provider supporting DSA
    at javax.crypto.Cipher.getInstance(DashoA13*..)

6.
javax.crypto.BadPaddingException: Given final block not properly padded
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
    at com.sun.crypto.provider.BlowfishCipher.engineDoFinal(DashoA13*..)
    at javax.crypto.Cipher.doFinal(DashoA13*..)
Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
    at com.sun.crypto.provider.BlowfishCipher.engineDoFinal(DashoA13*..)
    at javax.crypto.Cipher.doFinal(DashoA13*..)

7.
java.lang.IllegalStateException: Cipher not initialized
    at javax.crypto.Cipher.c(DashoA13*..)
    at javax.crypto.Cipher.doFinal(DashoA13*..)
Exception in thread "main" java.lang.IllegalStateException: Cipher not initialized
    at javax.crypto.Cipher.c(DashoA13*..)
    at javax.crypto.Cipher.doFinal(DashoA13*..)

8.
Exception in thread "main" java.security.InvalidKeyException: Illegal key size or default parameters
    at javax.crypto.Cipher.a(DashoA13*..)
    at javax.crypto.Cipher.a(DashoA13*..)
    at javax.crypto.Cipher.a(DashoA13*..)
    at javax.crypto.Cipher.init(DashoA13*..)
    at javax.crypto.Cipher.init(DashoA13*..)


9. Warnings

$javac SimpleCryptography.java

SimpleCryptography.java:6: warning: sun.misc.BASE64Decoder is Sun proprietary API and may be removed in a future release
import sun.misc.BASE64Decoder;
               ^
SimpleCryptography.java:7: warning: sun.misc.BASE64Encoder is Sun proprietary API and may be removed in a future release
import sun.misc.BASE64Encoder;
               ^
SimpleCryptography.java:24: warning: sun.misc.BASE64Encoder is Sun proprietary API and may be removed in a future release
        BASE64Encoder bASE64Encoder = new BASE64Encoder();
        ^
SimpleCryptography.java:24: warning: sun.misc.BASE64Encoder is Sun proprietary API and may be removed in a future release
        BASE64Encoder bASE64Encoder = new BASE64Encoder();
                                          ^
SimpleCryptography.java:35: warning: sun.misc.BASE64Decoder is Sun proprietary API and may be removed in a future release
                BASE64Decoder bASE64Decoder = new BASE64Decoder();
                ^
SimpleCryptography.java:35: warning: sun.misc.BASE64Decoder is Sun proprietary API and may be removed in a future release
                BASE64Decoder bASE64Decoder = new BASE64Decoder();
                                                  ^
6 warnings