/*
* Copyright (c) 2014-2015 Janith Bandara, This source is a part of
* Audit4j - An open source auditing framework.
* http://audit4j.org
*
* 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 org.audit4j.core.util;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import org.audit4j.core.CoreConstants;
import org.audit4j.core.handler.ConsoleAuditHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class SecurityUtil.
*
* @author <a href="mailto:janith3000@gmail.com">Janith Bandara</a>
*
* @since 1.0.2
*/
public class EncryptionUtil {
/** The log. */
private static final Logger LOG = LoggerFactory.getLogger(ConsoleAuditHandler.class);
/** The Constant ALGORYITHM. */
private static final String ALGORYITHM = "AES/CBC/PKCS5Padding";
/** The instance. */
private static EncryptionUtil instance;
/** The crypt key. */
private static Key cryptKey;
/**
* Instantiates a new encrypt util.
*/
private EncryptionUtil() {
}
/**
* Encrypt.
*
* @param raw the raw
* @return the string
* @throws IllegalBlockSizeException the illegal block size exception
* @throws BadPaddingException the bad padding exception
* @throws UnsupportedEncodingException the unsupported encoding exception
* @throws InvalidKeyException the invalid key exception
* @throws InvalidAlgorithmParameterException the invalid algorithm parameter exception
* @throws NoSuchAlgorithmException the no such algorithm exception
* @throws NoSuchPaddingException the no such padding exception
*/
public String encrypt(String raw) throws IllegalBlockSizeException, BadPaddingException,
UnsupportedEncodingException, InvalidKeyException, InvalidAlgorithmParameterException,
NoSuchAlgorithmException, NoSuchPaddingException {
Cipher c = getCipher(Cipher.ENCRYPT_MODE);
byte[] encryptedVal = c.doFinal(raw.getBytes(CoreConstants.ENCODE_UTF8));
return new String(Base64Coder.encode(encryptedVal));
}
/**
* Decrypt.
*
* @param encrypted
* the encrypted
* @return the string
* @throws Exception
* the exception
*/
public String decrypt(String encrypted) throws Exception {
byte[] decodedValue = Base64Coder.decode(encrypted.toCharArray());
Cipher c = getCipher(Cipher.DECRYPT_MODE);
byte[] decValue = c.doFinal(decodedValue);
return new String(decValue);
}
/**
* Gets the cipher.
*
* @param mode the mode
* @return the cipher
* @throws InvalidKeyException the invalid key exception
* @throws InvalidAlgorithmParameterException the invalid algorithm parameter exception
* @throws UnsupportedEncodingException the unsupported encoding exception
* @throws NoSuchAlgorithmException the no such algorithm exception
* @throws NoSuchPaddingException the no such padding exception
*/
private Cipher getCipher(int mode) throws InvalidKeyException, InvalidAlgorithmParameterException,
UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException {
Cipher c = Cipher.getInstance(ALGORYITHM);
byte[] iv = CoreConstants.IV.getBytes(CoreConstants.ENCODE_UTF8);
c.init(mode, cryptKey, new IvParameterSpec(iv));
return c;
}
/**
* Generate key.
*
* @param key
* the key
* @param salt
* the salt
* @return the key
* @throws NoSuchAlgorithmException
* the no such algorithm exception
* @throws UnsupportedEncodingException
* the unsupported encoding exception
* @throws InvalidKeySpecException
* the invalid key spec exception
*/
private static void generateKeyIfNotAvailable(String key, String salt) throws NoSuchAlgorithmException,
UnsupportedEncodingException, InvalidKeySpecException {
if (null == cryptKey) {
LOG.debug("Generating Key...");
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
char[] password = key.toCharArray();
byte[] saltBytes = salt.getBytes(CoreConstants.ENCODE_UTF8);
KeySpec spec = new PBEKeySpec(password, saltBytes, 65536, 128);
SecretKey tmp = factory.generateSecret(spec);
byte[] encoded = tmp.getEncoded();
cryptKey = new SecretKeySpec(encoded, "AES");
}
}
/**
* Gets the Encryptor.
*
* @param key the key
* @param salt the salt
* @return the Encryptor
* @throws NoSuchAlgorithmException the no such algorithm exception
* @throws UnsupportedEncodingException the unsupported encoding exception
* @throws InvalidKeySpecException the invalid key spec exception
*/
public static EncryptionUtil getInstance(String key, String salt) throws NoSuchAlgorithmException,
UnsupportedEncodingException, InvalidKeySpecException {
if (instance == null) {
synchronized (EncryptionUtil.class) {
if (instance == null) {
instance = new EncryptionUtil();
generateKeyIfNotAvailable(key, salt);
}
}
}
return instance;
}
}