Problemas para encriptar y desencriptar

Hola a todos, he estado un poco alejado del foro, el último que leí fué la polémica que empezó con un estudiante que tubo que desarrollar una página web con AJAX y terminaron hablando de lenguajes de programación que ni siquiera sabia que existian (disculpen la ignorancia).

Bueno tengo un problema, estoy implementando una clase que encripta y desencripta texto, el código es el siguiente, espeor y me puedan ayudar

import java.io.UnsupportedEncodingException;

import java.security.InvalidKeyException;

import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;

import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;

public class Cifrado {
//public Cifrado() {
// super();
// }

public static void main(String[] args) throws Exception {
String encript=encripta("ayuda");
System.out.println("Encriptado "+encript);
String decrypt=desencripta(encript);
System.out.println("Yasta "+decrypt);
}

public static String encripta(String s){
Cipher ecipher;
try {

SecretKey key = KeyGenerator.getInstance("DES").generateKey();
ecipher = Cipher.getInstance("DES");
ecipher.init(Cipher.ENCRYPT_MODE, key);

byte[] utf8 = s.getBytes("UTF8");
byte[] enc = ecipher.doFinal(utf8);
return new sun.misc.BASE64Encoder().encode(enc);
}catch (javax.crypto.BadPaddingException e) { }
catch (IllegalBlockSizeException e) { }
catch (UnsupportedEncodingException e) { }
catch (java.io.IOException e) { }
catch(NoSuchPaddingException l){l.printStackTrace();}
catch(NoSuchAlgorithmException i){i.printStackTrace();}
catch(InvalidKeyException p){p.printStackTrace();}
return "";

}

public static String desencripta(String s){
Cipher ecipher;
System.out.println("Valor pasado "+s);
try {

ecipher = Cipher.getInstance("DES");
SecretKey key = KeyGenerator.getInstance("DES").generateKey();
ecipher.init(Cipher.DECRYPT_MODE, key);

byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(s);
byte[] utf8 = ecipher.doFinal(dec);

return new String(utf8, "UTF8");
} catch (javax.crypto.BadPaddingException e) {e.printStackTrace(); }
catch (IllegalBlockSizeException e) {e.printStackTrace(); }
catch (UnsupportedEncodingException e) {e.printStackTrace(); }
catch (java.io.IOException e) { e.printStackTrace();}
catch(NoSuchPaddingException l){l.printStackTrace();}
catch(NoSuchAlgorithmException i){i.printStackTrace();}
catch(InvalidKeyException p){p.printStackTrace();}

return null;
}
}

y el error en el log es el siguiente

Encriptado zHjkOBTykEo=
Valor pasado zHjkOBTykEo=
javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.DESCipher.engineDoFinal(DashoA13*..)
at javax.crypto.Cipher.doFinal(DashoA13*..)
at mb.view.backing.Cifrado.desencripta(Cifrado.java:67)
at mb.view.backing.Cifrado.main(Cifrado.java:27)
Yasta null

Bueno espero y me puedan ayudar con este pequeño problema, de ante mano gracias y un saludo...!!!

Comentarios

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

Padding

No definiste ningún padding. Lee bien la documentación de las clases criptográficas de Java. Simplemente con que pases el padding y el modo de encadenamiento que quieres usar es suficiente, p.ej. DES/CFB/PKCS5Padding o si te vas a aventar el padding a manita pues DES/CFB/NoPadding. Si no tienes idea de qué es el padding entonces necesitas leer más a fondo de los conceptos de encripción simétrica por bloques. En cuanto al modo, si no usas ECB vas a tener que usas un vector de inicialización.

Espero que esto sea un ejercicio que estás haciendo para aprender algo de cifrado de datos; en la práctica ese código no sirve para cifrar datos a largo plazo a menos que también guardes la llave en algún lado, porque la estás generando de manera aleatoria y en cada corrida del programa se genera una llave distinta; si guardas la cadena cifrada de una corrida, no la podrás descifrar en la siguiente corrida porque no tienes la llave (encripción simétrica; para descifrar los datos necesitas la misma llave que usaste para cifrarlos).

Imagen de Gustavo

Listo...!!!!

Hola ezamudio gracias por responder, ya leí sobre el tema y pude resolver el problema, exáxtamente, guardo la llave en un archivo dentro del Sistema, así quedó el código:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

import java.io.IOException;

import java.io.UnsupportedEncodingException;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.KeySpec;
import java.security.spec.InvalidKeySpecException;

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.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

public class Encriptacion {
public Encriptacion() {
super();
}

public static String encrypt(String pass, String ruta, String file ){
Cipher ecipher;
try{
SecretKey key = KeyGenerator.getInstance("DES").generateKey();
guardaKey(key, ruta, file);
ecipher = Cipher.getInstance("DES");
ecipher.init(Cipher.ENCRYPT_MODE, key);

byte[] utf8 = pass.getBytes("UTF8");
byte[] enc = ecipher.doFinal(utf8);
return new sun.misc.BASE64Encoder().encode(enc);
}catch(NoSuchPaddingException e){e.printStackTrace();}
catch(NoSuchAlgorithmException e){e.printStackTrace();}
catch(InvalidKeyException e){e.printStackTrace();}
catch(UnsupportedEncodingException e){e.printStackTrace();}
catch(IllegalBlockSizeException e){e.printStackTrace();}
catch(BadPaddingException e){e.printStackTrace();}
return null;
}

public static String decrypt(String ruta, String file, String s){
Cipher ecipher;
SecretKey key=readKey(ruta, file);
if(key==null)return null;
try{
ecipher = Cipher.getInstance("DES");
ecipher.init(Cipher.DECRYPT_MODE, key);

byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(s);
byte[] utf8 = ecipher.doFinal(dec);

return new String(utf8, "UTF8");
}catch(NoSuchPaddingException e){e.printStackTrace();}
catch(NoSuchAlgorithmException e){e.printStackTrace();}
catch(InvalidKeyException e){e.printStackTrace();}
catch(UnsupportedEncodingException e){e.printStackTrace();}
catch(IllegalBlockSizeException e){e.printStackTrace();}
catch(BadPaddingException e){e.printStackTrace();}
catch(IOException e){e.printStackTrace();}
return null;
}

public static void main(String[] args) throws Exception {
KeyGenerator keyGen = KeyGenerator.getInstance("DES");
keyGen.init(56);
SecretKey secretKey = keyGen.generateKey();
String file="usuario";
String ruta="/root/Oracle/Middleware/GenKey";
//guardaKey(secretKey,file, ruta);
//readKey(ruta, file);
String pass="Mi password";
String encrStr=encrypt(pass, ruta, file);
System.out.println("Encriptado: "+encrStr);
String decrStr=decrypt(ruta, file, encrStr);
System.out.println("Desencriptado: "+decrStr);

/*
Cipher cifrador= Cipher.getInstance("DES/ECB/PKCS5Padding");
cifrador.init(Cipher.ENCRYPT_MODE, secretKey);
String mensaje = "Este el texto que se va a cifrar";
byte[] mensajeCifrado = cifrador.doFinal(mensaje.getBytes(), 0, mensaje.getBytes().length);
*/
}

public static void imprimeKey(SecretKey key){
System.out.println("**** Impresion **");
System.out.println("Algoritmo "+key.getAlgorithm());
System.out.println("To String "+key.toString());
}

public static void guardaKey(SecretKey key, String ruta, String fileName){
imprimeKey(key);

String fl=ruta+"/"+fileName+".key";
System.out.println("Ruta hasta el archivo "+fl);
try{
FileOutputStream fos = new FileOutputStream(fl);
byte[] kb = key.getEncoded();
fos.write(kb);
fos.close();

}catch(FileNotFoundException e){e.printStackTrace();}
catch(IOException e){e.printStackTrace();}

}

public static SecretKey readKey(String ruta, String fileName){
String fl=ruta+"/"+fileName+".key";
KeySpec ks = null;
SecretKey ky = null;
SecretKeyFactory kf = null;
try{
FileInputStream fis = new FileInputStream(fl);
int kl = fis.available();
byte[] kb = new byte[kl];
fis.read(kb);
fis.close();

ks = new DESKeySpec(kb);
kf = SecretKeyFactory.getInstance("DES");
ky = kf.generateSecret(ks);
imprimeKey(ky);
}catch(FileNotFoundException e){e.printStackTrace();}
catch(IOException e){e.printStackTrace();}
catch(InvalidKeyException e){e.printStackTrace();}
catch(NoSuchAlgorithmException e){e.printStackTrace();}
catch(java.security.spec.InvalidKeySpecException e){e.printStackTrace();}
return ky;
}

}

si tienes alguna sugerencia más es bienvenida. Un Saludo...!!!

Imagen de ezamudio

Seguridad

OK ya te peleaste con los algoritmos y las clases de criptografía de Java. Ya pudiste generar una llave aleatoria y con eso cifrar datos, guardar la llave en disco. Ahora tienes que pensar si eso realmente te da algo de seguridad.

Quién tiene acceso a ese archivo donde está la llave?
El problema que pretendes solucionar con esto, realmente se soluciona? No funcionaría mejor encripción asimétrica?
Los datos que vas a cifrar, para quién son accesibles (aunque sea cifrados)? Porque estás usando DES, ni siquiera Triple-DES, y es una llave de 56 bits efectivos; un ataque de fuerza bruta con una computadora actual "normalita" toma muy poco tiempo.

A lo que voy es que no creas que por usar encripción ya están seguros los datos. Necesitas hacer un muy buen análisis (tú o el arquitecto de software a cargo del proyecto, o algun asesor externo, etc) de la seguridad que requieren tener y luego se van a la implementación. Hoy en día DES como lo estás implementando te ofrece un poquitito más de seguridad que ROT13.

Imagen de Gustavo

Gracias..!!

Muchas gracias Ezamudio, son buenos estos retos, estube leyendo un poco, si me pudieras mencionar algún método de encriptacion aimétrica y enforcarme a ese, de ante mano gracias y estudiaré un poco mas sobre el metodo que me popongas, en un post posterior pondré la clase sobre ese método... Gracias...!!!