org.craftercms.commons.crypto.SimpleCipher Maven / Gradle / Ivy
/*
* Copyright (C) 2007-2014 Crafter Software Corporation.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package org.craftercms.commons.crypto;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.StringUtils;
import org.craftercms.commons.i10n.I10nLogger;
import org.craftercms.commons.i10n.I10nUtils;
/**
* Utility class for simplifying encryption/decryption with the {@link javax.crypto.Cipher} class. By default, the
* algorithm used is AES.
*
* @author Sumer Jabri
* @author Alfonso Vásquez
*/
public class SimpleCipher {
public static final String LOG_KEY_ENC_SUCCESSFUL = "crypto.cipher.encryptionSuccessful";
public static final String LOG_KEY_DEC_SUCCESSFUL = "crypto.cipher.decryptionSuccessful";
public static final String LOG_KEY_KEY_GEN = "crypto.cipher.keyGenerated";
public static final String LOG_KEY_IV_GEN = "crypto.cipher.ivGenerated";
public static final String LOG_KEY_DEF_CIPHER_CREATED = "crypto.cipher.defaultCipherCreated";
public static final String ERROR_KEY_KEY_NOT_SET = "crypto.cipher.keyNotSet";
public static final String ERROR_KEY_IV_NOT_SET = "crypto.cipher.ivNotSet";
public static final String ERROR_KEY_ENC_ERROR = "crypto.cipher.encryptionError";
public static final String ERROR_KEY_DEC_ERROR = "crypto.cipher.decryptionError";
private static final I10nLogger logger = new I10nLogger(SimpleCipher.class, I10nUtils.DEFAULT_LOGGING_MESSAGE_BUNDLE_NAME);
private Key key;
private byte[] iv;
private Cipher cipher;
public Key getKey() {
return key;
}
public void setKey(Key key) {
this.key = key;
}
public byte[] getIv() {
return iv;
}
public void setIv(byte[] iv) {
this.iv = iv;
}
public Cipher getCipher() {
return cipher;
}
public void setCipher(Cipher cipher) {
this.cipher = cipher;
}
public String encryptBase64(String clear) throws CryptoException {
return Base64.encodeBase64String(encrypt(StringUtils.getBytesUtf8(clear)));
}
public byte[] encrypt(byte[] clear) throws CryptoException {
if (key == null) {
key = CryptoUtils.generateAesKey();
logger.debug(LOG_KEY_KEY_GEN);
}
if (iv == null) {
iv = CryptoUtils.generateAesIv();
logger.debug(LOG_KEY_IV_GEN);
}
if (cipher == null) {
cipher = createDefaultCipher();
}
try {
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
return cipher.doFinal(clear);
} catch (GeneralSecurityException e) {
throw new CryptoException(ERROR_KEY_ENC_ERROR, e);
} finally {
logger.debug(LOG_KEY_ENC_SUCCESSFUL);
}
}
public String decryptBase64(String encrypted) throws CryptoException {
return StringUtils.newStringUtf8(decrypt(Base64.decodeBase64(encrypted)));
}
public byte[] decrypt(byte[] encrypted) throws CryptoException {
if (key == null) {
throw new CryptoException(ERROR_KEY_KEY_NOT_SET);
}
if (iv == null) {
throw new CryptoException(ERROR_KEY_IV_NOT_SET);
}
if (cipher == null) {
cipher = createDefaultCipher();
}
try {
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
return cipher.doFinal(encrypted);
} catch (GeneralSecurityException e) {
throw new CryptoException(ERROR_KEY_DEC_ERROR, e);
} finally {
logger.debug(LOG_KEY_DEC_SUCCESSFUL);
}
}
protected Cipher createDefaultCipher() {
String cipherTransformation = CryptoUtils.DEFAULT_AES_CIPHER_TRANSFORMATION;
try {
return Cipher.getInstance(cipherTransformation);
} catch (NoSuchPaddingException | NoSuchAlgorithmException e) {
// Should NEVER happen
throw new IllegalStateException("JVM doesn't support " + cipherTransformation, e);
} finally {
logger.debug(LOG_KEY_DEF_CIPHER_CREATED, cipherTransformation);
}
}
}