com.asquareb.kaaval.MachineKey.java Source code

Java tutorial

Introduction

Here is the source code for com.asquareb.kaaval.MachineKey.java

Source

/* 
* Author: Biju Nair
# Github: https://github.com/bijugs
#
# License
# =======
#
# [Apache 2.0 license](http://www.apache.org/licenses/LICENSE-2.0)
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either expressed or implied. See the license for the specific
# language governing permissions and limitations under the license.
#
# Copyright (c) 2015 The Authors, All Rights Reserved.
*/

package com.asquareb.kaaval;

/**
 * The function of this class is to encrypt a string using password based 
 * encryption. Requires some implementation of Base64 encoder/decoder like
 * org.apache.commons.codec package available in Apache commons-codec-x.x.jar
 */

import java.io.*;
import java.util.Random;
import java.net.InetAddress;
import java.net.NetworkInterface;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

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

/**
 * Java class to create a key file during encryption. The key file is required
 * to decrypt the value in an encrypted form
 */
class MachineKey implements Serializable {

    private static final long serialVersionUID = 1L;

    protected SecretKey yek = null;

    protected String api = null;

    protected String macad = null;

    protected byte[] tlas = null;

    protected int eti;
}

/**
 * Class to encrypt and decrypt strings. Uses PBE based crypto to do encrypt and
 * decrypt. This can be run as a command line utility and the methods can be
 * individually called from a JAVA program Need to have an implementation of
 * Base64 CODEC in the class path. For e.g the commons-codec-1.5.jar file from
 * Apache.
 */
public class ProtectedConfigFile {

    /**
     * Variable to store the password entered by the user to encrypt the
     * password string. It need to be converted into a Character array for to be
     * used by the encrypt method
     */
    private static char[] password;

    /**
     * Byte array of length 8 to be used as SALT for PBE based encryption and
     * decryption methods
     */
    private static byte[] salt = new byte[8];

    /**
     * Main method to execute as a command line utility. Provides the option to
     * encrypt a string, decrypt a encrypted string or exit from the program
     */
    public static void main(String[] args) {
        String originalPassword = null;
        String encryptedPassword = null;
        try {
            final BufferedReader cin = new BufferedReader(new InputStreamReader(System.in));
            System.out.print("Enter E - Encrypt,D - Decrypt,X - Exit :");
            final String choice = cin.readLine();
            final Random rand = new Random();
            boolean phraseCorrect = false;
            String app = null;
            if (choice.equalsIgnoreCase("E")) {
                System.out.print("Enter the string to encrypt :");
                originalPassword = cin.readLine();
                System.out.println("Choose a phrase of min 8 chars in length ");
                System.out.println(" Also the password should include 2 Cap,");
                System.out.println(" 2 small letters,2 numeric and 2 non alpha numeric chars");
                while (!phraseCorrect) {
                    System.out.print("Enter a phrase to encrypt :");
                    password = cin.readLine().toCharArray();
                    phraseCorrect = PasswordRules.verifyPassword(password);
                }
                System.out.print("Enter application code :");
                app = cin.readLine();
                app += (rand.nextInt(10000));
                encryptedPassword = encrypt(originalPassword, app);
                System.out.println("Encrypted password :" + encryptedPassword);
                System.out.println("Key stored in :" + app);
                System.out.println("*** Provide the encrypted string to app team");
                System.out.println("*** Store the key file in a secure durectory");
                System.out.println("*** Inform the key file name and location to app team");
            } else if (choice.equalsIgnoreCase("D")) {
                System.out.print("Enter the string to Decrypt :");
                encryptedPassword = cin.readLine();
                System.out.print("Enter the name of key file :");
                app = cin.readLine();
                final String decryptedPassword = decrypt(encryptedPassword, app);
                System.out.print("Decrypted string :" + decryptedPassword);
            }
            return;
        } catch (KaavalException e) {
            e.PrintProtectException();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Method to encrypt a string. Accepts the string to be encrypted and the
     * name of the file to store the key vale which can be used for decryption
     */
    public static String encrypt(String property, String app) throws IOException, KaavalException {

        InetAddress ip = null;
        String ipAddress = null;
        ObjectOutputStream os = null;
        NetworkInterface macAddress = null;
        byte[] macId = null;
        Cipher pbeCipher = null;
        Random rand = new Random();
        rand.nextBytes(salt);
        try {
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
            SecretKey key = keyFactory.generateSecret(new PBEKeySpec(password));
            ip = InetAddress.getLocalHost();
            ipAddress = ip.getHostAddress();
            macAddress = NetworkInterface.getByInetAddress(ip);
            macId = macAddress.getHardwareAddress();
            MachineKey mKey = new MachineKey();
            mKey.api = ipAddress;
            mKey.macad = new String(macId);
            mKey.yek = key;
            mKey.tlas = salt;
            mKey.eti = rand.nextInt(1000);
            os = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(app)));
            os.writeObject(mKey);
            os.close();
            pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
            pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(salt, mKey.eti));
            return base64Encode(pbeCipher.doFinal(property.getBytes()));
        } catch (IOException e) {
            throw new KaavalException(1, "Error in key file during encryption", e);
        } catch (Exception e) {
            throw new KaavalException(2, "Errors during encryption", e);
        } finally {
            if (os != null)
                os.close();
        }
    }

    /**
     * Method to encode bytes to strings. Uses Apache implementation of Base 64
     * CODEC
     */
    private static String base64Encode(byte[] bytes) {
        return Base64.encodeBase64String(bytes);
    }

    /**
     * Method to decrypt a string. Accepts the string to be decrypted and the
     * name of the file which stores the key values
     */
    public static String decrypt(String property, String app) throws IOException, KaavalException {
        SecretKey key = null;
        ObjectInputStream is = null;
        MachineKey mKey = null;
        int eti = 0;
        Cipher pbeCipher = null;
        InetAddress ip = InetAddress.getLocalHost();
        NetworkInterface macAddress = NetworkInterface.getByInetAddress(ip);
        byte[] macId = macAddress.getHardwareAddress();
        try {
            is = new ObjectInputStream(new BufferedInputStream(new FileInputStream(app)));
            mKey = (MachineKey) is.readObject();
            key = mKey.yek;
            salt = mKey.tlas;
            eti = mKey.eti;
            String ipa = ip.getHostAddress();
            if (!ipa.equals(mKey.api) || !new String(macId).equals(mKey.macad))
                throw new KaavalException(5, "Key file is not for this machine");
            is.close();
            pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
            pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(salt, eti));
            return new String(pbeCipher.doFinal(base64Decode(property)));
        } catch (IOException e) {
            throw new KaavalException(3, "Error in reading key file during decryption", e);
        } catch (KaavalException e) {
            throw e;
        } catch (Exception e) {
            throw new KaavalException(4, "Error during decryption", e);
        } finally {
            if (is != null)
                is.close();
        }
    }

    /**
     * Method to decode string to bytes. Uses Apache implementation of Base 64
     * CODEC
     */
    private static byte[] base64Decode(String property) throws IOException {
        return new Base64().decode(property);
    }
}