com.vmware.bdd.security.EncryptionGuard.java Source code

Java tutorial

Introduction

Here is the source code for com.vmware.bdd.security.EncryptionGuard.java

Source

/***************************************************************************
 * Copyright (c) 2012-2013 VMware, Inc. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     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 express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ***************************************************************************/
package com.vmware.bdd.security;

import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.Key;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;

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

import com.vmware.aurora.exception.CommonException;
import com.vmware.bdd.exception.EncryptionException;
import com.vmware.bdd.utils.AuAssert;

public class EncryptionGuard {

    private static final String UTF8_ENCODING = "UTF8";

    // explicitly declare algorithm, block mode, padding mode.
    // once need to change them, change the internal methods if necessary.
    private static final String ALGORITHM = "AES";
    private static final String BLOCK_MODE = "CBC";
    private static final String PADDING = "PKCS5Padding";
    private static final String TRANSFORMATION = ALGORITHM + "/" + BLOCK_MODE + "/" + PADDING;

    // initialization vector required for CBC
    private static final byte[] IV_PARAMETER = { (byte) 0x51, (byte) 0x2c, (byte) 0x3a, (byte) 0xb4, (byte) 0x87,
            (byte) 0xa0, (byte) 0xa1, (byte) 0x79, (byte) 0x56, (byte) 0x73, (byte) 0x56, (byte) 0x7d, (byte) 0xc2,
            (byte) 0x1f, (byte) 0xeb, (byte) 0x73 };

    // fix salt size
    private static final int SALT_SIZE = 16;

    /**
     * Encrypt the clear text against given secret key.
     * 
     * @param clearText
     *           the clear string
     * @return the encrypted string, or null if the clear string is null
     * @throws CommonException
     *            if input arguments is null
     */
    public static String encode(String clearText) throws GeneralSecurityException, UnsupportedEncodingException {
        if (clearText == null) {
            return null;
        }

        Key key = GuardKeyStore.getEncryptionKey();
        String salt = SaltGenerator.genRandomString(SALT_SIZE);

        String inputText = salt + clearText; // add salt
        byte[] clearBytes = inputText.getBytes(UTF8_ENCODING);

        Cipher cipher = getCiperInternal(Cipher.ENCRYPT_MODE, key);
        byte[] encryptedBytes = cipher.doFinal(clearBytes);

        Base64 base64 = new Base64(0); // 0 - no chunking
        return salt + base64.encodeToString(encryptedBytes);
    }

    /**
     * Decrypt the encrypted text against given secret key.
     * 
     * @param encodedText
     *           the encrypted string
     * @return the clear string, or null if encrypted string is null
     * @throws CommonException
     *            if input arguments is null
     */
    public static String decode(String encodedText) throws GeneralSecurityException, UnsupportedEncodingException {
        if (encodedText == null) {
            return null;
        }

        if (encodedText.length() < SALT_SIZE) {
            throw EncryptionException.SHORT_ENCRYPTED_STRING(encodedText);
        }

        Key key = GuardKeyStore.getEncryptionKey();
        String salt = encodedText.substring(0, SALT_SIZE);
        String encryptedText = encodedText.substring(SALT_SIZE);

        Base64 base64 = new Base64(0); // 0 - no chunking
        byte[] encryptedBytes = base64.decode(encryptedText);

        Cipher cipher = getCiperInternal(Cipher.DECRYPT_MODE, key);
        byte[] outputBytes = cipher.doFinal(encryptedBytes);

        String outputText = new String(outputBytes, UTF8_ENCODING);
        AuAssert.check(salt.equals(outputText.substring(0, SALT_SIZE))); // Assert salt

        return outputText.substring(SALT_SIZE);
    }

    /**
     * Get a cipher instance when need it, not share between multiple threads
     * because cipher is not thread safe.
     * 
     * @param opmode
     *           the operation mode
     * @param key
     *           the key
     * @return initialized cipher instance
     */
    private static Cipher getCiperInternal(int opmode, Key key) throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        IvParameterSpec ips = new IvParameterSpec(IV_PARAMETER, 0, 16);
        cipher.init(opmode, key, ips);
        return cipher;
    }
}