com.tesora.dve.common.PECryptoUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.tesora.dve.common.PECryptoUtils.java

Source

package com.tesora.dve.common;

/*
 * #%L
 * Tesora Inc.
 * Database Virtualization Engine
 * %%
 * Copyright (C) 2011 - 2014 Tesora Inc.
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License, version 3,
 * as published by the Free Software Foundation.
 * 
 * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
 * #L%
 */

import java.lang.reflect.Field;
import java.security.spec.KeySpec;

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.Base64;
import org.apache.commons.lang.StringUtils;

import com.tesora.dve.exceptions.PEException;

public final class PECryptoUtils {

    private static final CryptoSettings settings = buildSettings();

    private static CryptoSettings buildSettings() {
        Class<?> c = null;
        try {
            c = Class.forName("com.tesora.dve.common.DVEPrivateCryptoSettings");
        } catch (ClassNotFoundException cnfe) {
            c = DVEPublicCryptoSettings.class;
        }
        return new CryptoSettings(c);
    }

    private PECryptoUtils() {
    }

    private static Cipher createCrypter(int mode) throws Exception {
        // Create the key
        KeySpec keySpec = new PBEKeySpec(settings.getPassword().toCharArray(), settings.getSalt(),
                settings.getIterations());
        SecretKey key = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(keySpec);

        Cipher cipher = Cipher.getInstance(key.getAlgorithm());

        cipher.init(mode, key, new PBEParameterSpec(settings.getSalt(), settings.getIterations()));

        return cipher;
    }

    public static String encrypt(String str) throws PEException {
        if (StringUtils.isBlank(str))
            return str;

        try {
            Cipher cipher = createCrypter(Cipher.ENCRYPT_MODE);

            byte[] enc = cipher.doFinal(str.getBytes("UTF8"));

            return new String(Base64.encodeBase64(enc));
        } catch (Exception e) {
            throw new PEException("Failed to encrypt '" + str + "'", e);
        }
    }

    public static String decrypt(String str) throws PEException {
        if (StringUtils.isBlank(str))
            return str;

        try {
            Cipher cipher = createCrypter(Cipher.DECRYPT_MODE);

            return new String(cipher.doFinal(Base64.decodeBase64(str)), "UTF8");
        } catch (Exception e) {
            throw new PEException("Failed to decrypt '" + str + "'", e);
        }
    }

    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.println("Usage: " + PECryptoUtils.class.getName() + " <password>");
            return;
        }

        try {
            System.out.println();
            System.out.println("  " + args[0] + " ==> " + encrypt(args[0]));
            System.out.println();
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

    private static final class CryptoSettings {

        private final int iterations;
        private final String password;
        private final byte[] salt;

        private final Throwable failed;
        private final Class<?> source;

        private CryptoSettings(Class<?> c) {
            this.source = c;
            int iterVal = 0;
            String pVal = null;
            byte[] sVal = null;
            Throwable any = null;
            try {
                Field iterField = c.getDeclaredField("iterations");
                Field pField = c.getDeclaredField("password");
                Field sField = c.getDeclaredField("salt");

                iterVal = (Integer) iterField.get(null);
                pVal = (String) pField.get(null);
                sVal = (byte[]) sField.get(null);
            } catch (Throwable t) {
                any = t;
            }
            this.iterations = iterVal;
            this.password = pVal;
            this.salt = sVal;
            this.failed = any;
        }

        private final void fail() {
            if (failed != null)
                throw new IllegalStateException("Unable to obtain DVE crypto settings from " + source.getName());
        }

        final int getIterations() {
            fail();
            return iterations;
        }

        final String getPassword() {
            fail();
            return password;
        }

        final byte[] getSalt() {
            fail();
            return salt;
        }
    }
}