package com.im.imjutil.cipher;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.MessageDigest;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import com.im.imjutil.exception.CipherException;
import com.im.imjutil.exception.InstantiateException;
import com.im.imjutil.exception.OperationException;
import com.im.imjutil.validation.Convert;
/**
* Classe abstrata responsavel por codificar e decodificar bytes usando
* um dos diversos algoritmos disponiveis.
* @see {@link CipherType}
*
* @author Bruno de Alcantara, Felipe Zappala
*/
public abstract class Cipher {
/** Define a chave secreta para codificar e decodificar uma mensagem. */
protected byte[] password;
/** Define o codificador padrao. */
private static Cipher cipherDefault = getInstance();
/**
* Retorna uma intancia de {@link Cipher} para o algoritmo
* do tipo {@link CipherType#DEFAULT}.
*/
public static final Cipher getInstance() {
return getInstance(CipherType.DEFAULT);
}
/**
* Retorna uma intancia de {@link Cipher} para o algoritmo
* do tipo {@link CipherType}.
*/
public static final Cipher getInstance(CipherType type)
throws InstantiateException {
if (type == null) {
throw new InstantiateException("O tipo passado e nulo");
}
Class<? extends Cipher> clazz = type.clazz;
if (clazz == null) {
throw new InstantiateException(Convert.toString(
"Tipo de codificador nao implementado: ", type.cipher));
}
Cipher instance = null;
try {
try {
Constructor<? extends Cipher> constructor;
constructor = clazz.getConstructor(CipherType.class);
instance = constructor.newInstance(type);
} catch (NoSuchMethodException e) {
instance = clazz.newInstance();
}
} catch (java.lang.InstantiationException e) {
throw new InstantiateException("Erro ao instanciar o codificador",e);
} catch (IllegalAccessException e) {
throw new InstantiateException("Erro ao acessar o codificador",e);
} catch (InvocationTargetException e) {
throw new InstantiateException("Erro ao construir o codificador",e);
} catch (Exception e) {
throw new InstantiateException(Convert.toString(
"Excecao desconhecida: ", e.getClass().getName(),
" -> ", e.getMessage()), e);
}
return instance;
}
/**
* Compara se os bytes passados sao iguais
*/
public static final boolean isEqual(byte[] cipher1, byte[] cipher2) {
if (cipher1 != null && cipher2 != null) {
return MessageDigest.isEqual(cipher1, cipher2);
}
return false;
}
/**
* Retorna a representacao String hexadecimal do byte[] passado.
*/
public static final String asHex(byte[] bytes) {
return Convert.toHexadecimal(bytes);
}
/**
* Retorna a representacao byte[] da String hexadecimal passada.
*/
public static final byte[] asBytes(String hex) {
return Convert.toHexabytes(hex);
}
/**
* Gera uma senha aleatoria e segura para o tipo de
* algoritmo de criptografia passado.
*/
public static final byte[] generatePassword(CipherType type)
throws OperationException {
try {
KeyGenerator kgen = KeyGenerator.getInstance(type.cipher);
SecretKey skey = kgen.generateKey();
return skey.getEncoded();
} catch (Exception e) {
throw new OperationException(Convert.toString(
e.getClass().getName(), " -> ", e.getMessage()), e);
}
}
/**
* Codifica os bytes passados pelo algoritmo padrao configurado.
*/
public static byte[] defaultEncrypt(byte[] value) throws CipherException {
return cipherDefault.encrypt(value);
}
/**
* Decodifica os bytes passados pelo algoritmo padrao configurado.
*/
public static byte[] defaultDecrypt(byte[] value) throws CipherException {
return cipherDefault.decrypt(value);
}
/**
* Codifica os bytes passados pelo algoritmo configurado.
*/
public abstract byte[] encrypt(byte[] value) throws CipherException;
/**
* Decodifica os bytes passados pelo algoritmo configurado.
*/
public abstract byte[] decrypt(byte[] value) throws CipherException;
/**
* Obtem a senha (chave secreta ou privada) de criptografia.
*/
public byte[] getPassword() {
return password;
}
/**
* Configura a senha (chave secreta ou privada) de criptografia.
*/
public void setPassword(byte[] password) {
if (password != null) {
this.password = password;
}
}
}