Package com.salesforce.dataloader.security

Source Code of com.salesforce.dataloader.security.EncryptionUtil

/*
* Copyright (c) 2012, salesforce.com, inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided
* that the following conditions are met:
*
*    Redistributions of source code must retain the above copyright notice, this list of conditions and the
*    following disclaimer.
*
*    Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
*    the following disclaimer in the documentation and/or other materials provided with the distribution.
*
*    Neither the name of salesforce.com, inc. nor the names of its contributors may be used to endorse or
*    promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package com.salesforce.dataloader.security;

import org.apache.log4j.Logger;

import java.io.*;
import java.security.*;
import java.security.spec.InvalidKeySpecException;

import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;

public class EncryptionUtil {

    private static final Logger LOGGER = Logger.getLogger(EncryptionUtil.class);
    private Key gKey = null;
    private String gCipherSeed = "namastearrigato";
    private String gCipherKey = "51dda30be226233d";

    public EncryptionUtil() {
    }

    /**
     *
     */
    synchronized public void resetCryptoKey() {
        gKey = null;
        gCipherKey = null;
    }

    /**
     * @param sKey
     */
    synchronized public void setCipherKey(String sKey) {
        gCipherKey = sKey;
    }

    /**
     * Convert text to bytes
     *
     * @param text
     * @return bytes for the input text
     */
    private static byte[] textToBytes(String text) {
        byte[] baBytes = new byte[text.length() / 2];
        for (int j = 0; j < text.length() / 2; j++) {
            Integer tmpInteger = Integer.decode(new String("0x" + text.substring(j * 2, (j * 2) + 2)));
            int tmpValue = tmpInteger.intValue();
            if (tmpValue > 127) // fix negatives
            {
                tmpValue = (tmpValue - 127) * -1;
            }
            tmpInteger = new Integer(tmpValue);
            baBytes[j] = tmpInteger.byteValue();
        }

        return baBytes;
    }

    /**
     * Convert bytes to text
     *
     * @param bytes
     * @return text for the input bytes
     */
    private static String bytesToText(byte[] bytes) {
        StringBuffer sb = new StringBuffer(bytes.length * 2);
        for (int i = 0; i < bytes.length; i++) {
            int num = bytes[i];
            if (num < 0) num = 127 + (num * -1); // fix negative back to positive
            String hex = Integer.toHexString(num);
            if (hex.length() == 1) {
                hex = "0" + hex; // ensure 2 digits
            }
            sb.append(hex);
        }

        return sb.toString();
    }

    /**
     * Create a key for encryption and decryption
     *
     * @return Key
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     * @throws InvalidKeyException
     */
    synchronized private Key getCryptoKey() throws NoSuchAlgorithmException, InvalidKeySpecException,
    InvalidKeyException {
        if (gKey != null) return gKey;

        String sKeyText = gCipherKey != null ? gCipherKey : generateKey(gCipherSeed);
        byte[] baKeyBytes = textToBytes(sKeyText);

        try {
            SecretKeyFactory desFactory = SecretKeyFactory.getInstance("DES");
            gKey = desFactory.generateSecret(new DESKeySpec(baKeyBytes));
        } catch (InvalidKeyException e) {
            throw e;
        } catch (InvalidKeySpecException e) {
            throw e;
        }

        return gKey;
    }

    /**
     * Create the cipher object for encryption or decryption. We create a DES cipher with PKCS#5 padding
     *
     * @return Cipher
     * @throws NoSuchAlgorithmException
     * @throws NoSuchPaddingException
     */
    private static Cipher createCipher() throws NoSuchAlgorithmException, NoSuchPaddingException {
        try {
            return Cipher.getInstance("DES/ECB/PKCS5Padding");
        } catch (NoSuchAlgorithmException e) {
            throw e;
        } catch (NoSuchPaddingException e) {
            throw e;
        }
    }

    /**
     * Encrypt a string using whatever is the default encryption technique for the system.
     *
     * @param clearText
     * @return The encrypted string
     * @throws GeneralSecurityException
     */
    public String encryptString(String clearText) throws GeneralSecurityException {
        if (clearText == null) return clearText;
        Key oKey = getCryptoKey();
        Cipher oCipher = createCipher();
        byte[] encryptedBytes;

        if (oCipher == null) { return clearText; }

        byte[] inputBytes = clearText.getBytes();

        try {
            oCipher.init(Cipher.ENCRYPT_MODE, oKey);
        } catch (InvalidKeyException e) {
            throw e;
        }

        try {
            encryptedBytes = oCipher.doFinal(inputBytes);
        } catch (IllegalBlockSizeException e) {
            throw e;
        } catch (BadPaddingException e) {
            throw e;
        }

        return bytesToText(encryptedBytes);
    }

    /**
     * Decrypt a string using whatever is the default encryption technique for the system.
     *
     * @param cipherText
     * @return The decrypted string
     * @throws NoSuchPaddingException
     * @throws NoSuchAlgorithmException
     * @throws BadPaddingException
     * @throws IllegalBlockSizeException
     * @throws InvalidKeyException
     */
    public String decryptString(String cipherText) throws GeneralSecurityException {
        if (cipherText == null) return cipherText;
        Key key = getCryptoKey();
        Cipher cipher = createCipher();

        if (cipher == null) { return cipherText; }

        try {
            cipher.init(Cipher.DECRYPT_MODE, key);
        } catch (InvalidKeyException e) {
            throw e;
        }

        byte[] baCipherBytes = textToBytes(cipherText);

        try {
            return new String(cipher.doFinal(baCipherBytes));
        } catch (BadPaddingException e) {
            throw e;
        } catch (IllegalBlockSizeException e) {
            throw e;
        }
    }

    /**
     * Create a DES key and return a string version of the raw bits.
     *
     * @param seed
     * @return A key for encryption
     * @throws NoSuchAlgorithmException
     */
    public static String generateKey(String seed) throws NoSuchAlgorithmException {

        byte[] seedBytes = seed.getBytes();
        SecureRandom random = new SecureRandom(seedBytes);
        KeyGenerator keygen = null;
        try {
            keygen = KeyGenerator.getInstance("DES");
        } catch (NoSuchAlgorithmException e) {
            throw e;
        }

        keygen.init(random);
        Key key = keygen.generateKey();

        byte[] keyBytes = key.getEncoded();

        return bytesToText(keyBytes);
    }

    /**
     * @param keyFilename
     * @throws IOException
     */
    public void setCipherKeyFromFilePath(String keyFilename) throws IOException {
        try {
            File keyFile = new File(keyFilename);
            if (keyFile.exists() && keyFile.canRead()) {
                FileReader fr = new FileReader(keyFile);
                BufferedReader br = new BufferedReader(fr);
                String line = null;
                while ((line = br.readLine()) != null) {
                    break;
                }
                if (line != null) {
                    resetCryptoKey(); // Reset Key
                    setCipherKey(line);
                }
            } else {
                throw new IOException("Cannot Access Key File: " + keyFilename);
            }
        } catch (IOException e) {
            throw e;
        }
    }

    private static void printUsage() {
        LOGGER.info("\nUtility to encrypt a string based on a static or a provided key");
        LOGGER.info("Options (mutually exclusive - use one at a time): \n"
                + "\t-g <seed text>                                 Generate key based on seed\n"
                + "\t-v <encrypted> <decrypted value> [Path to Key] Validate whether decryption of encrypted value matches the decrypted value, optionally provide key file\n"
                + "\t-e <plain text> [Path to Key]                  Encrypt a plain text value, optionally provide key file (generate key using option -g)");
    }

    public static void main(String[] args) {
        // args[0] = input data, required
        // args[1] = key (optional)
        if (args.length < 1) {
            printUsage();
            System.exit(-1);
        }

        int i = 0;
        String option = args[i];
        if (option.length() < 2 || option.charAt(0) != '-') {
            LOGGER.info("Invalid option format: " + args[i]);
            System.exit(-1);
        }
        // make sure enough arguments are provided
        if (arrayTooSmall(args, i)) {
            LOGGER.info("Option '" + option + "' requires at least one parameter.  Please check usage.\n");
            printUsage();
            System.exit(-1);
        }
        // advance index to param and save the param value
        String param = args[++i];
        switch (option.charAt(1)) {
            case 'g':
                try {
                    String key = generateKey(param);
                    LOGGER.info(key);
                } catch (NoSuchAlgorithmException e) {
                    LOGGER.error("Error generating key: " + e.getMessage());
                    System.exit(-1);
                }
                break;
            case 'v':
                // verify if encrypted value matches the encrypted the encrypted
                // cleartext
                // if optional key file is provided, use it
                if (arrayTooSmall(args, i)) {
                    LOGGER.info("Please provide decrypted value to validate against");
                    printUsage();
                    System.exit(-1);
                }
                String decryptExpected = args[++i];
                EncryptionUtil dec = new EncryptionUtil();
                if (!arrayTooSmall(args, i)) {
                    try {
                        dec.setCipherKeyFromFilePath(args[++i]);
                    } catch (IOException e) {
                        LOGGER.error("Error setting the key from file: "
                                + args[i] + ", error: " + e.getMessage());
                        System.exit(-1);
                    }
                }
                try {
                    String decrypted = dec.decryptString(param);
                    LOGGER.info("Decryption of encrypted value "
                            + (decryptExpected.equals(decrypted) ? "MATCHES"
                            : "DOES NOT MATCH") + " the expected value");
                } catch (GeneralSecurityException e) {
                    LOGGER.error("Error decrypting string: " + param
                            + ", error: " + e.getMessage());
                    System.exit(-1);
                }
                break;
            case 'e':
                // if optional key file is provided, use it
                EncryptionUtil enc = new EncryptionUtil();
                if (!arrayTooSmall(args, i)) {
                    String keyFilename = args[++i];
                    File keyFile = new File(keyFilename);
                    if (!keyFile.exists() && !keyFile.canRead()) {
                        LOGGER.warn("Please ensure that the key file '"
                                + keyFilename + "' exists and is readable");
                        printUsage();
                        System.exit(-1);
                    }
                    try {
                        enc.setCipherKeyFromFilePath(keyFilename);
                    } catch (IOException e) {
                        LOGGER.error("Error setting the key from file: "
                                + keyFilename + ", error: " + e.getMessage());
                        System.exit(-1);
                    }
                }
                try {
                    // encrypt the given string and output to STDOUT
                    String encrypted;
                    encrypted = enc.encryptString(param);
                    LOGGER.info(encrypted);
                } catch (GeneralSecurityException e) {
                    LOGGER.error("Error encrypting string: " + param
                            + ", error: " + e.getMessage());
                    System.exit(-1);
                }
                break;
            default:
                LOGGER.error("Unsupported option: " + option);
                printUsage();
                System.exit(-1);
        }
    }

    /**
     * @param array
     * @param index
     * @return true if array is too small to increment the index
     */
    private static boolean arrayTooSmall(String[] array, int index) {
        return (index + 1) > (array.length - 1);
    }
}
TOP

Related Classes of com.salesforce.dataloader.security.EncryptionUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.