1.- Creamos una clase AESKey
Esta clase solamente contendra una variable que sera nuestra key, que nos servira para encriptar y desencriptar
public class AESKey { private String encoded; public String getEncoded() { return encoded; } public void setEncoded(String encoded) { this.encoded = encoded; } }
2.- Primero crearemos nuestra clase encriptacion
public class AESEncriptacion { //el resto del codigo ira aqui :) }
3.- Crearemos nuestro metodo crearKey
private final String ALGORITMO = "AES";//algoritmo (si cambia la imprementacion tambien) private final int LONGITUD = 128;//longitud de la llave () private final String CODIFICACION = "UTF-8";//como se convertira a byte, esto sera mas adelante /** Agrego un constructor que recibe como parametros un AESKey */ public AESEncriptacion(AESKey aesKey) throws Exception { this.aesKey = aesKey; } public AESKey generaKey() throws Exception { KeyGenerator kgen = KeyGenerator.getInstance(ALGORITMO); kgen.init(LONGITUD); SecretKey skey = kgen.generateKey(); AESKey aesKey = new AESKey(); aesKey.setEncoded(StringtoHex(skey.getEncoded())); return aesKey; }
4.- Crearemos nuestro metodo Encriptacion
/** Estoy delegando las exepciones a el metodo que ocupe a encripta. Convierto una cadena, q en este caso es mi key a un arreglo de bytes el cual se lo asigno junto con el algoritmo a la clase SecretKeySpec. Obtengo una instancia de Chiper en base al algoritmo, esta me ayudara a encriptar y desencriptar mis codigos A mi variable chiper la pongo en modo encripcion y le paso mi key secreta Obtengo un arreglo de bytes que representa a mi cadena encriptada (resultado de la encripcion) Para que pueda guardar por ejemplo en bd mi cadena encriptada, paso el arreglo de bytes a una cadena, esto lo hago con ayuda del metodo hexToString que veremos mas adelante */ public String encripta(String cadena) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException { byte[] raw = StringToHex(aesKey.getEncoded()); SecretKeySpec skeySpec = new SecretKeySpec(raw, ALGORITMO); Cipher cipher = Cipher.getInstance(ALGORITMO); cipher.init(Cipher.ENCRYPT_MODE, skeySpec); byte[] encrypted = cipher.doFinal(cadena.getBytes(CODIFICACION)); String encriptado = HexToString(encrypted); return encriptado; }
5.- Crearemos nuestro metodo HexToString
/** Por medio de un for recorro cada posicion del arreglo de bytes En la variable aux obtengo la posicion deseada, indicando que es un hexadecimal por medio de 0xff Como un hexadecimal lo representare con 2 poficiones ff, 0f, 12... etc en caso de que el resultado fuera menor a 16 solo obtendria 1 posicion lo que me daria problemas al momento de desencriptar En caso de ser menor a 16, le concateno un 0 a mi cadena, luego simplemente concateno mi variable aux, indicando que la guardate en un formato String que representara un hexadecimal > Integer.toHexString(aux) Al Final retorno una cadena que representa a mi arreglo de bytes, de esta forma podre guardar la informacion en una bd, o imprimirla de una forma entendible */ private String HexToString(byte[] arregloEncriptado) { String textoEncriptado = ""; for (int i = 0; i < arregloEncriptado.length; i++) { int aux = arregloEncriptado[i] & 0xff; if (aux < 16) { textoEncriptado = textoEncriptado.concat("0"); } textoEncriptado = textoEncriptado.concat(Integer.toHexString(aux)); } return textoEncriptado; }
6.- Crearemos nuestro metodo StringToHex
/** Creo un arreglo de bytes, del tamaño de mi cadena / 2 (por eso el agregar un 0 si hera menor a 16 en el metodo de HexToString) Por medio de un for recorro a mi arreglo Dentro del fofr en la variable index guardare la posicion * 2, esto para siempre tomar pares 2, 4, 6, etc... En la variable aux guardo un subString de index a index+2 (0-2,2-4) siempre sera en pares, no hay fallas por que el metodo HexToString me retorno una cadena par En una variable int, guardo el parseo del segmento de cadena, con base 16 (Hexadecimal) Para finalizar en la posocion correspondiente de mi arreglo de bytes hago un cast para guardar mi variable entera Finalmente retornaria un arreglo de bytes identico al que recibio el metodo HexToString, por tanto obtengo mi arreglo encriptado :) */ private byte[] StringToHex(String encriptado) { byte[] enBytes = new byte[encriptado.length() / 2]; for (int i = 0; i < enBytes.length; i++) { int index = i * 2; String aux = encriptado.substring(index, index + 2); int v = Integer.parseInt(aux, 16); enBytes[i] = (byte) v; } return enBytes; }7.- Crearemos nuestro metodo Desencripcion
/** Del mismo modo delego las excepciones a un nivel superior Obtengo un arreglo de bytes a partir de mi key Se lo asigno junto con el algoritmo a la clase SecretKeySpec. Obtengo una instancia de Chiper en base al algoritmo A mi variable chiper la pongo en modo desencripcion y le paso mi key secret Obtengo un arreglo de bytes a partir de mi cadena encriptada Al final creo un String a partir de mi arreglo de bytes Esto no lo hice antes, como algunos ejemplos de la red, por que ? por que de este modo si lo hiciera desde el metodo encriptar, habria algunos caracteres que no se podrian representar, por lo tanto se perderia la integridad de la informacion. Es mas pueden intentar realizar el programa sin utilizar HexToString y StringToHex haciendo las conversiones del tipo new String(byte[]) y no trabajaria su codigo */ public String desencriptar(String encriptado) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException { byte[] raw = StringToHex(aesKey.getEncoded()); SecretKeySpec skeySpec = new SecretKeySpec(raw, ALGORITMO); Cipher cipher = Cipher.getInstance(ALGORITMO); cipher.init(Cipher.DECRYPT_MODE, skeySpec); byte[] original = cipher.doFinal(StringToHex(encriptado)); String originalString = new String(original); return originalString; }8.- Crearemos nuestro Implementacion
public static void main(String args[]) throws Exception { AESKey aesKey = new AESKey(); AESEncriptacion tmp = new AESEncriptacion(); aesKey = tmp.generaKey(); AESEncriptacion ejemplo = new AESEncriptacion(aesKey); String encriptado = ejemplo.encripta("123456789012345678"); String desencriptado = ejemplo.desencriptar(encriptado); System.out.println(encriptado); System.out.println(desencriptado); }
9.- Se me olvidava, te coloco los importes por si las moscas :)
import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.KeyGenerator; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec;
NOTA: Al final De una Forma Ligeramente Simple podemos encriptar utilizando el Algoritmo AES, En posteriores post colocare otras formas de encripcion
Sin miedo ! ! !
hola, este codigo esta muy bien, pero hay muchos errores... por ejemplo en la linia 17 del paso 3. subid codigo depurado, porque si no la gente pierde mucho tiempo. gracias
ResponderEliminar/**
ResponderEliminar*
* @author Menta
*/
public class AlgoritmoAes {
public static void main(String[] args) {
AESKey aesKey = new AESKey();
AESEncriptacion tmp = new AESEncriptacion(aesKey);
aesKey = tmp.generaKey();
AESEncriptacion ejemplo = new AESEncriptacion(aesKey);
String encriptado = ejemplo.encripta("123456789012345678");
String desencriptado = ejemplo.desencriptar(encriptado);
System.out.println(encriptado);
System.out.println(desencriptado);
}
}
Te pongo el codigo depurado correctamente.
Aitor_@hotmail.es
www.supercodigo.es
public class AESEncriptacion {
ResponderEliminarprivate final String ALGORITMO = "AES";//algoritmo (si cambia la imprementacion tambien)
private final int LONGITUD = 128;//longitud de la llave ()
private final String CODIFICACION = "UTF-8";//como se convertira a byte, esto sera mas adelante
private AESKey aesKey;
public AESEncriptacion(AESKey aesKey) {
this.aesKey = aesKey;
}
public AESKey generaKey() {
KeyGenerator kgen = null;
try {
kgen = KeyGenerator.getInstance(ALGORITMO);
} catch (NoSuchAlgorithmException ex) {
error(ex);
}
kgen.init(LONGITUD);
SecretKey skey = kgen.generateKey();
aesKey = new AESKey();
aesKey.setEncoded(HexToString(skey.getEncoded()));
return aesKey;
}
public String encripta(String cadena) {
String encriptado = null;
try {
byte[] raw = StringToHex(aesKey.getEncoded());
SecretKeySpec skeySpec = new SecretKeySpec(raw, ALGORITMO);
Cipher cipher = Cipher.getInstance(ALGORITMO);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(cadena.getBytes(CODIFICACION));
encriptado = HexToString(encrypted);
} catch (IllegalBlockSizeException ex) {
error(ex);
} catch (BadPaddingException ex) {
error(ex);
} catch (UnsupportedEncodingException ex) {
error(ex);
} catch (InvalidKeyException ex) {
error(ex);
} catch (NoSuchAlgorithmException ex) {
error(ex);
} catch (NoSuchPaddingException ex) {
error(ex);
}
return encriptado;
}
private String HexToString(byte[] arregloEncriptado) {
String textoEncriptado = "";
for (int i = 0; i < arregloEncriptado.length; i++) {
int aux = arregloEncriptado[i] & 0xff;
if (aux < 16) {
textoEncriptado = textoEncriptado.concat("0");
}
textoEncriptado = textoEncriptado.concat(Integer.toHexString(aux));
}
return textoEncriptado;
}
private byte[] StringToHex(String encriptado) {
byte[] enBytes = new byte[encriptado.length() / 2];
for (int i = 0; i < enBytes.length; i++) {
int index = i * 2;
String aux = encriptado.substring(index, index + 2);
int v = Integer.parseInt(aux, 16);
enBytes[i] = (byte) v;
}
return enBytes;
}
public String desencriptar(String encriptado) {
String originalString = null;
try {
byte[] raw = StringToHex(aesKey.getEncoded());
SecretKeySpec skeySpec = new SecretKeySpec(raw, ALGORITMO);
Cipher cipher = Cipher.getInstance(ALGORITMO);
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] original = cipher.doFinal(StringToHex(encriptado));
originalString = new String(original);
} catch (IllegalBlockSizeException ex) {
error(ex);
} catch (BadPaddingException ex) {
error(ex);
} catch (InvalidKeyException ex) {
error(ex);
} catch (NoSuchAlgorithmException ex) {
error(ex);
} catch (NoSuchPaddingException ex) {
error(ex);
}
return originalString;
}
private void error(Exception ex) {
System.err.print(ex.getMessage());
}
}
Aitor_@hotmail.es
www.supercodigo.es
los imports de la clase anterior
ResponderEliminarimport java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class AESKey {
ResponderEliminarprivate String encoded;
public String getEncoded() {
return encoded;
}
public void setEncoded(String encoded) {
this.encoded = encoded;
}
}
Aitor_@hotmail.es
www.supercodigo.es
No funciona... si utilizo la variable tmp.. para desencriptar "dc2c6001eb5a83ed4730faa6e13b566c" no lo hace simplemente devuelve null... solo funciona en caso de que el texto que vaya a desencriptar sea un texto que ya encripte anteriormente usando esa misma variable.. lo cual no me satisface la necesidad.. porque estoy leyendo lo encriptado desde la bd.
ResponderEliminarEse es el punto, solo poder desencriptar con la misma semilla con la cual encriptaste la información, de otro modo se pierde el sentido de encriptar algo que con cualquier semilla pueda ser decodificado.
ResponderEliminarEn algún lugar debe estar la semilla con la cual se encripto la información de tu bd. si no es el mismo caso. para eso tendrías que utilizar un método de desencriptacion que es cosa diferente a lo escrito en esta entrada.
saludos.
como encripto un texto con clave??
ResponderEliminarcon clave se esta encriptando 123456789012345678
ResponderEliminarpero en donde puedo modificar la clave?, o en este caso cual es la clave?
EliminarEste comentario ha sido eliminado por el autor.
ResponderEliminarQue tal gracias por pasar por el blog !, intente replicar el error pero no pude hacerlo, lo que si es que vi 2 errores en el código original.
EliminarPor lo tanto en unos instantes subiré la clase completa ya arreglada y comentando donde cometí errores la ves que hice este post
ya esta la actualización del código, y gracias por la observación.
EliminarMuchas gracias voy a probar de nuevo, y te comento. :)
Eliminar