Decrypt. AES JAVA. Two errors: Given final block not properly padded

1

I have to perform encryption and decryption through AES. Encryption gives me good, but it is deciphering gives me problems. There's no way, I've been a week now.

This is the code:

public  class Cifrar {

// Definición del tipo de algoritmo a utilizar (AES, DES, RSA)
private final static String alg = "AES";
private final static int keyLength=128;
private final static int ivLength=128;

// Definición del modo de cifrado a utilizar
private final static String cI =  "AES/CBC/PKCS5Padding";



// Aqui generamos la clave aleatoria AES
public static byte [] ClaveAleatoria() throws Exception {
        //Generamos la clave aleatoria.
        KeyGenerator keyGen = KeyGenerator.getInstance(alg);
        keyGen.init(keyLength, new SecureRandom());
        SecretKey aesKey = keyGen.generateKey();
        byte[] aesKeyBytes = aesKey.getEncoded();
        return aesKeyBytes;

}



       public static  byte[] VectorInicialAleatorio() throws Exception {   
        byte [] iv = SecureRandom.getSeed(ivLength/8);
        return iv;

     }





public static byte[] encrypt( byte [] aesKeyBytes, byte[]  iv , String cleartext) throws Exception {
        Cipher cipher = Cipher.getInstance(cI);
        //SecretKeySpec skeySpec = new SecretKeySpec(aesKeyBytes.getBytes(), alg);
        SecretKeySpec skeySpec = new SecretKeySpec(aesKeyBytes, alg);
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
        //System.out.println(ivParameterSpec);
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivParameterSpec);
        byte[] encrypted = cipher.doFinal(cleartext.getBytes());
        //return new String(encodeBase64(encrypted));
        //return new String(Base64.encode(encrypted));
        return encrypted;
}







     //AQUI ESTA EL PROBLEMAA- PARECE QUE LE FALTAN BYTES

    public static String decrypt(byte [] aesKeyBytes, byte[]  iv, byte[] encrypted) throws Exception {
        Cipher cipher = Cipher.getInstance(cI);
        SecretKeySpec skeySpec = new SecretKeySpec(aesKeyBytes, alg);
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
        //byte[] enc = Base64.encode(encrypted);
        System.out.println(encrypted+"aqui despues viene el fallo");
        //byte[] enc = Base64.decode(encrypted);

        cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivParameterSpec);
        //byte[] decrypted = cipher.doFinal(enc);
        byte[] decrypted = cipher.doFinal(encrypted);
        return new String(decrypted);
}

 }

This is the main

public class main {

     public static void main(String[] args) throws Exception {

     String cleartext = "hola";

    byte[] textocifrado= 



 crypto.Cifrar.encrypt(crypto.Cifrar.ClaveAleatoria(),crypto.Cifrar.VectorInicialAleatorio(),cleartext);

   System.out.println("Texto encriptado: "+textocifrado);
   System.out.println("Texto desencriptado: "+crypto.Cifrar.decrypt(crypto.Cifrar.ClaveAleatoria(),crypto.Cifrar.VectorInicialAleatorio(),textocifrado));

When I execute it tells me:

Texto encriptado: ����ߏ�Ϻ��Qθ�
Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded
����ߏ�Ϻ��Qθ�aqui despues viene el fallo
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:313)
    at javax.crypto.Cipher.doFinal(Cipher.java:2087)
    at crypto.Cifrar.decrypt(Cifrar.java:129)
    at crypto.main.main(main.java:24)
C:\Users\Jurpark\AppData\Local\NetBeans\Cache.1\executor-snippets\run.xml:53: Java returned: 1
BUILD FAILED (total time: 1 second)
    
asked by Solid 29.05.2017 в 13:54
source

1 answer

1

DO NOT convert byte[] to String unless you're sure that% byte[] corresponds to a String (for example, after decrypting a value that was originally a String ).

A String in Java is coded in UTF-8, which means that not all possible values are valid. You simply can not be sure that going from byte[] to String and back to byte[] will return the original value.

If the byte[] represents the content of a String , the conversion can be done without problems (eg, if you get the byte[] of a String , the conversion back to String does not present problems ); after all, that byte[] already represents the String in the correct format. So:

new String("hola".getBytes()); // te devuelve un nuevo String con el texto "hola".

The point is that not all byte [] will represent String s .

Also, it does not make much sense, since a String represents a text value while a byte[] represents binary data.

Solution: Do not convert; work with byte[] directly.

Once this point is clarified, the calls you make to your methods are:

crypto.Cifrar.encrypt(
    crypto.Cifrar.ClaveAleatoria(),
    crypto.Cifrar.VectorInicialAleatorio(),
    cleartext);

crypto.Cifrar.decrypt(
    crypto.Cifrar.ClaveAleatoria(),
    crypto.Cifrar.VectorInicialAleatorio(),
    textocifrado))

That is, you call the ClaveAleatoria() 1 method once for each function . Unless you always generate the same key (I doubt it very much), you are trying to decrypt with a different key than the one used to encrypt . And, precisely, the objective of an encryption function is that it is impossible.

Save the key you are going to use in a variable and pass it to both methods.

1 In Java, method names, variables and attributes always begin with a lowercase .     
answered by 29.05.2017 в 14:10