com.mb.framework.util.SecurityUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.mb.framework.util.SecurityUtil.java

Source

/**
 * Copyright (C) 2013 Company. All Rights Reserved. 
 * 
 * This software is the proprietary information of Company . 
 * Use is subjected to license terms. 
 *
 * @since Jul 14, 2013 8:27:33 PM
 * @author SPA
    
 *
 */

package com.mb.framework.util;

import java.io.UnsupportedEncodingException;
import java.security.AlgorithmParameters;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

import com.mb.framework.util.log.LogHelper;

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

/**
 * @author SPA
 * 
 */
@SuppressWarnings("restriction")
public class SecurityUtil {
    private static final LogHelper LOGGER = LogHelper.getInstance("SecurityUtil");

    private static final String AES_CBC_PKCS5PADDING_ALGO = "AES/CBC/PKCS5Padding";
    private static final String SECRET_KEY = "test";
    private static String salt;
    private static int pswdIterations = 65536;
    private static int keySize = 128; //Nirenj updated to 128
    private static byte[] ivBytes;

    private static final String AES_ALGO = "AES";

    // SecretKeySpec - AES allows 128, 192 or 256 bit key length. That is 16, 24
    // or 32 byte.( :- 16, 24 or 32 length of byte array )
    // Needs to keep SecretKey safe

    // 128 bit length of secret key(16 byte) private static final byte[]
    private static final byte[] KEY_VALUE_128_BIT = new byte[] { 'T', 'h', 'e', 'B', 'e', 's', 't', 'S', 'e', 'c',
            'r', 'e', 't', 'K', 'e', 'y' };

    // 192 bit length of secret key(24 byte) private static final byte[]
    //   private static final byte[] KEY_VALUE_192_BIT = new byte[] { 'T', 'h', 'e',
    //         'B', 'e', 's', 't', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y',
    //         'T', 'h', 'e', 'B', 'e', 's', 't', 'S', };
    //
    //   // 256 bit length of secret key(32 byte)
    //   private static final byte[] KEY_VALUE_256_BIT = new byte[] { 'T', 'h', 'e',
    //         'B', 'e', 's', 't', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y',
    //         'T', 'h', 'e', 'B', 'e', 's', 't', 'S', 'e', 'c', 'r', 'e', 't',
    //         'K', 'e', 'y', };

    /********************** START - MD5 **********************/
    /**
     * This method encrypts the password as per Md5 Algorithm.
     * 
     * @param String
     * @return String
     * 
     */
    public static String encryptMd5(String plaintext) throws Exception {
        MessageDigest md = null;

        try {
            md = MessageDigest.getInstance("SHA"); // step 2
        } catch (NoSuchAlgorithmException e) {
            throw new Exception(e.getMessage());
        }

        try {
            md.update(plaintext.getBytes("UTF-8")); // step 3
        } catch (UnsupportedEncodingException e) {
            throw new Exception(e.getMessage());
        }

        byte raw[] = md.digest(); // step 4
        return new BASE64Encoder().encode(raw); // step 5
    }

    /************************* END - MD5 ***********************/

    /********************** START - ASE_ALGO *******************/

    /**
     * 
     * This method is used for encrypt by using Algorithm - AES
     * 
     * @param String
     * @return String
     * @throws Exception
     */
    public static String encryptAES(String data) throws Exception {

        Key key = generateKeyAES(); // step 1

        Cipher c = Cipher.getInstance(AES_ALGO); // step 2
        c.init(Cipher.ENCRYPT_MODE, key); // step 3

        byte[] encVal = c.doFinal(data.getBytes()); // step 4
        String encryptedValue = new BASE64Encoder().encode(encVal); // step 5

        return encryptedValue;
    }

    /**
     * 
     * This method is used for decrypt by using Algorithm - AES
     * 
     * @param String
     * @return String
     * @throws Exception
     */
    public static String decryptAES(String encryptedData) throws Exception {

        Key key = generateKeyAES(); // step 1

        Cipher c = Cipher.getInstance(AES_ALGO); // step 2
        c.init(Cipher.DECRYPT_MODE, key); // step 3

        byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData); // step
        // 4
        byte[] decValue = c.doFinal(decordedValue); // step 5
        return new String(decValue);
    }

    private static Key generateKeyAES() {
        return new SecretKeySpec(KEY_VALUE_128_BIT, AES_ALGO);
    }

    /******************** END - ASE_ALGO *****************************/

    /********** START - 256-bit AES/CBC/PKCS5Padding (based on PKCS#5s PBKDF2) ************/

    /**
     * As per My Company SECURITY GUIDELINES How to fight against pre-computed look-up
     * tables? Use a salt Iterate many times (e.g. 50,000 times) e.g.
     * Hash(Hash(Hash(Hash(Hash(salt+credentials))))) Available solutions:
     * PBKDF2 (Password-Based Key Derivation Function #2) 256-bit AES (based on
     * PKCS#5s PBKDF2
     * 
     */

    /**
     * 
     * This method is used for encrypt by using Algorithm - AES/CBC/PKCS5Padding
     * 
     * @param String
     * @return String
     * @throws Exception
     */
    public static String encryptAESPBKDF2(String plainText) throws Exception {

        // get salt
        salt = generateSaltAESPBKDF2();
        byte[] saltBytes = salt.getBytes("UTF-8");

        // Derive the key
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        PBEKeySpec spec = new PBEKeySpec(SECRET_KEY.toCharArray(), saltBytes, pswdIterations, keySize);

        SecretKey secretKey = factory.generateSecret(spec);
        SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");

        // encrypt the message
        Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5PADDING_ALGO);
        cipher.init(Cipher.ENCRYPT_MODE, secret);
        AlgorithmParameters params = cipher.getParameters();
        ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV();
        byte[] encryptedTextBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
        return new Base64().encodeAsString(encryptedTextBytes);
    }

    /**
     * 
     * This method is used for decrypt by using Algorithm - AES/CBC/PKCS5Padding
     * 
     * @param String
     * @return String
     * @throws Exception
     */
    @SuppressWarnings("static-access")
    public static String decryptAESPBKDF2(String encryptedText) throws Exception {

        byte[] saltBytes = salt.getBytes("UTF-8");
        byte[] encryptedTextBytes = new Base64().decodeBase64(encryptedText);

        // Derive the key
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        PBEKeySpec spec = new PBEKeySpec(SECRET_KEY.toCharArray(), saltBytes, pswdIterations, keySize);

        SecretKey secretKey = factory.generateSecret(spec);
        SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");

        // Decrypt the message
        Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5PADDING_ALGO);
        cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(ivBytes));

        byte[] decryptedTextBytes = null;
        try {
            decryptedTextBytes = cipher.doFinal(encryptedTextBytes);
        } catch (IllegalBlockSizeException e) {

            LOGGER.error("error " + e.getMessage());
        } catch (BadPaddingException e) {
            LOGGER.error("error " + e.getMessage());
        }

        return new String(decryptedTextBytes);
    }

    /**
     * 
     * This method is used for generate slat
     * 
     * @param String
     * @return String
     * @throws Exception
     */
    public static String generateSaltAESPBKDF2() {
        SecureRandom random = new SecureRandom();
        byte bytes[] = new byte[20];
        random.nextBytes(bytes);
        return new String(bytes);
    }

    /************ END - 256-bit AES/CBC/PKCS5Padding (based on PKCS#5s PBKDF2) **********/

    /**
     * Thisis main method to run program
     * 
     * @param args
     *            []
     */
    public static void main(String args[]) {

        try {
            Security.addProvider(new com.sun.crypto.provider.SunJCE());// step 1
            // PasswordUtil passwordEncryptAgent = new PasswordUtil("ASCII");
            String password = "Abcd@1234";
            System.out.println("Plain Password : " + password + "\n");

            /******************************* START - MD5 *****************************************/
            System.out.println("MD5 - Encrypted Password:  " + encryptMd5(password) + "\n");
            /******************************* END - MD5 *******************************************/

            /******************************* START - ASE_ALGO ************************************/
            String passwordEnc = encryptAES(password);
            String passwordDec = decryptAES(passwordEnc);

            System.out.println("ASE - Encrypted Password : " + passwordEnc);
            System.out.println("ASE - Decrypted Password : " + passwordDec + "\n");
            /******************************* END - ASE_ALGO ************************************/

            /****** START - 256-bit AES/CBC/PKCS5Padding (based on PKCS#5s PBKDF2) ************/

            String encryptedText = encryptAESPBKDF2(password);
            System.out.println(
                    "256-bit AES/CBC/PKCS5Padding (based on PKCS#5s PBKDF2) - Encrypted string:" + encryptedText);
            System.out.println("256-bit AES/CBC/PKCS5Padding (based on PKCS#5s PBKDF2) - Decrypted string:"
                    + decryptAESPBKDF2(encryptedText));

            /******** END - 256-bit AES/CBC/PKCS5Padding (based on PKCS#5s PBKDF2) ************/
        } catch (Exception ex) {
            LOGGER.error("error " + ex.getMessage());
        }

    }

}