org.paxml.util.CryptoUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.paxml.util.CryptoUtils.java

Source

/**
 * This file is part of PaxmlCore.
 *
 * PaxmlCore is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * PaxmlCore is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with PaxmlCore.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.paxml.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.UnsupportedEncodingException;
import java.security.KeyStore;
import java.security.KeyStore.PasswordProtection;
import java.security.KeyStoreException;
import java.security.MessageDigest;
import java.util.concurrent.Callable;

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

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.paxml.core.PaxmlRuntimeException;

import com.thoughtworks.xstream.core.util.Base64Encoder;

public class CryptoUtils {

    public static final String DEFAULT_KEY_STORE_NAME = "";
    public static final String DEFAULT_KEY_NAME = "";
    public static final String KEY_STORE_TYPE = "JCEKS";
    public static final String KEY_STORE_EXT = KEY_STORE_TYPE.toLowerCase();
    public static final int KEY_LENGTH_BITS = 128;
    public static final int KEY_LENGTH_BYTES = KEY_LENGTH_BITS / 8;
    public static final String KEY_STORE_FOLDER = "keys";
    public static final String KEY_TYPE = "AES";
    public static final String HASH_TYPE = "SHA-1";
    public static final String KEY_VALUE_ENCODING = "UTF-8";
    private static final String DEFAULT_KEY_PASSWORD = "key_pass";

    private static final RWTaskExecutor keyStoreExecutor = new RWTaskExecutor();

    private static SecretKey getSecretKey(String keyValue) {

        byte[] b;
        try {
            MessageDigest sha = MessageDigest.getInstance(HASH_TYPE);
            b = sha.digest(keyValue.getBytes(KEY_VALUE_ENCODING));
        } catch (Exception e) {
            throw new PaxmlRuntimeException(e);
        }
        byte[] kb = new byte[KEY_LENGTH_BYTES];
        // take the left 16 bytes part of the sha-1
        System.arraycopy(b, 0, kb, 0, kb.length);

        return new SecretKeySpec(kb, KEY_TYPE);

    }

    public static String base64Encode(byte[] data) {
        return new Base64Encoder().encode(data);
    }

    public static byte[] base64Decode(String data) {
        return new Base64Encoder().decode(data);
    }

    public static String hexEncode(byte[] data) {
        return new String(Hex.encodeHex(data));
    }

    public static byte[] hexDecode(String data) {
        try {
            return Hex.decodeHex(data.toCharArray());
        } catch (DecoderException e) {
            throw new PaxmlRuntimeException(e);
        }
    }

    public static byte[] encrypt(String data, String password) {

        SecretKey SecKey = getSecretKey(password);
        try {
            KeyGenerator KeyGen = KeyGenerator.getInstance(KEY_TYPE);
            KeyGen.init(KEY_LENGTH_BITS);

            Cipher cipher = Cipher.getInstance(KEY_TYPE);

            byte[] clear = data.getBytes(KEY_VALUE_ENCODING);

            cipher.init(Cipher.ENCRYPT_MODE, SecKey);
            return cipher.doFinal(clear);
        } catch (Exception e) {
            throw new PaxmlRuntimeException(e);
        }

    }

    public static String decrypt(byte[] data, String password) {
        SecretKey SecKey = getSecretKey(password);
        try {
            KeyGenerator KeyGen = KeyGenerator.getInstance(KEY_TYPE);
            KeyGen.init(KEY_LENGTH_BITS);

            Cipher cipher = Cipher.getInstance(KEY_TYPE);

            cipher.init(Cipher.DECRYPT_MODE, SecKey);
            byte[] clear = cipher.doFinal(data);
            return new String(clear, KEY_VALUE_ENCODING);
        } catch (Exception e) {
            throw new PaxmlRuntimeException(e);
        }
    }

    private static File getKeyStoreFile(String keyStoreName) {
        if (StringUtils.isBlank(keyStoreName)) {
            keyStoreName = DEFAULT_KEY_STORE_NAME;
        }
        String fileName = KEY_STORE_FOLDER + File.separatorChar + keyStoreName + "." + KEY_STORE_EXT;
        File file = PaxmlUtils.getFileUnderPaxmlHome(fileName, false);
        if (file == null) {
            file = PaxmlUtils.getFileUnderUserHome(fileName);
        }
        return file;
    }

    public static void changeKeyStorePassword(String keyStoreName, final String oldPassword,
            final String newPassword) {
        final File file = getKeyStoreFile(keyStoreName);
        final String key = file.getAbsolutePath();
        keyStoreExecutor.executeWrite(key, new Callable<Void>() {

            @Override
            public Void call() throws Exception {
                KeyStore keyStore = getKeyStore(file, oldPassword);
                saveKeyStore(file, newPassword, keyStore);
                return null;
            }
        });
    }

    public static String getKey(String keyStoreName, final String keyStorePassword, final String keyName,
            final String keyPassword) {
        final File file = getKeyStoreFile(keyStoreName);
        final String key = file.getAbsolutePath();
        return keyStoreExecutor.executeRead(key, new Callable<String>() {

            @Override
            public String call() throws Exception {
                KeyStore keyStore = getKeyStore(file, keyStorePassword);
                return getKey(keyStore, keyName, keyPassword);
            }
        });

    }

    private static String getKey(KeyStore keyStore, String keyName, String keyPassword) {
        if (StringUtils.isBlank(keyName)) {
            keyName = DEFAULT_KEY_NAME;
        }
        if (keyPassword == null) {
            keyPassword = DEFAULT_KEY_PASSWORD;
        }
        PasswordProtection _keyPassword = new PasswordProtection(keyPassword.toCharArray());
        KeyStore.Entry entry;
        try {
            if (!keyStore.containsAlias(keyName)) {
                return null;
            }
            entry = keyStore.getEntry(keyName, _keyPassword);
        } catch (Exception e) {
            throw new PaxmlRuntimeException(e);
        }
        SecretKey key = ((KeyStore.SecretKeyEntry) entry).getSecretKey();
        try {
            return new String(key.getEncoded(), KEY_VALUE_ENCODING);
        } catch (UnsupportedEncodingException e) {
            throw new PaxmlRuntimeException(e);
        }

    }

    public static boolean deleteKeyStore(String keyStoreName) {
        final File file = getKeyStoreFile(keyStoreName);
        return keyStoreExecutor.executeWrite(file.getAbsolutePath(), new Callable<Boolean>() {

            @Override
            public Boolean call() throws Exception {
                return file.delete();
            }

        });

    }

    public static void deleteKey(String keyStoreName, final String keyStorePassword, final String keyName) {
        final File file = getKeyStoreFile(keyStoreName);
        keyStoreExecutor.executeWrite(file.getAbsolutePath(), new Callable<Void>() {

            @Override
            public Void call() throws Exception {
                deleteKey(getKeyStore(file, keyStorePassword), keyName);
                return null;
            }

        });
    }

    private static void deleteKey(KeyStore keyStore, String keyName) {
        try {
            if (keyStore.containsAlias(keyName)) {
                keyStore.deleteEntry(keyName);
            }
        } catch (KeyStoreException e) {
            throw new PaxmlRuntimeException(e);
        }
    }

    public static void setKey(String keyStoreName, final String keyStorePassword, final String keyName,
            final String keyPassword, final String keyValue) {
        final File file = getKeyStoreFile(keyStoreName);
        final String key = file.getAbsolutePath();
        keyStoreExecutor.executeWrite(key, new Callable<Void>() {

            @Override
            public Void call() throws Exception {

                KeyStore keyStore = getKeyStore(file, keyStorePassword);
                setKey(keyStore, keyName, keyPassword, keyValue);
                saveKeyStore(file, keyStorePassword, keyStore);
                return null;
            }
        });
    }

    private static void setKey(KeyStore keyStore, String keyName, String keyPassword, String keyValue) {
        if (StringUtils.isBlank(keyName)) {
            keyName = DEFAULT_KEY_NAME;
        }
        if (keyPassword == null) {
            keyPassword = DEFAULT_KEY_PASSWORD;
        }
        try {
            SecretKey secretKey = new SecretKeySpec(keyValue.getBytes(KEY_VALUE_ENCODING), KEY_TYPE);

            KeyStore.SecretKeyEntry keyStoreEntry = new KeyStore.SecretKeyEntry(secretKey);
            PasswordProtection _keyPassword = new PasswordProtection(keyPassword.toCharArray());
            keyStore.setEntry(keyName, keyStoreEntry, _keyPassword);

        } catch (Exception e) {
            throw new PaxmlRuntimeException(e);
        }

    }

    private static void saveKeyStore(final File file, final String password, final KeyStore ks) {
        file.delete();
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);
            ks.store(fos, password.toCharArray());
        } catch (Exception e) {
            throw new PaxmlRuntimeException("Cannot write to key store file: " + file.getAbsolutePath(), e);
        } finally {
            IOUtils.closeQuietly(fos);
        }

    }

    private static KeyStore getKeyStore(final File file, final String password) {
        final String key = file.getAbsolutePath();

        KeyStore keyStore;

        final char[] pwd = password.toCharArray();
        if (!file.exists()) {
            FileOutputStream fos = null;
            try {
                file.getParentFile().mkdirs();
                fos = new FileOutputStream(file);
                // keystore file not created yet => create it
                keyStore = KeyStore.getInstance(KEY_STORE_TYPE);
                keyStore.load(null, null);
                keyStore.store(fos, pwd);
            } catch (Exception e) {
                throw new PaxmlRuntimeException("Cannot create new key store file: " + key, e);
            } finally {
                IOUtils.closeQuietly(fos);
            }
        }
        FileInputStream fis = null;

        try {
            fis = new FileInputStream(file);
            keyStore = KeyStore.getInstance(KEY_STORE_TYPE);
            // keystore file already exists => load it
            keyStore.load(fis, pwd);

        } catch (Exception e) {
            throw new PaxmlRuntimeException("Cannot read from key store file: " + key, e);
        } finally {
            IOUtils.closeQuietly(fis);
        }

        return keyStore;

    }

}