Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AES Encryption and Decryption with Java

Here is what I am doing which can look a bit clumsy but any help is appreciated regarding the problem. I'm getting a BadPaddingException. Read almost all related topics but didn't find the appropriate solution. I am new to encryption decryption programming and need to implement it in one of my Java application.

Thank You.. this is how the code looks....

public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
    // TODO Auto-generated method stub
            String FileName="encryptedtext.txt";
            String FileName2="decryptedtext.txt";
            String pad="0"; 

            KeyGenerator KeyGen=KeyGenerator.getInstance("AES");
            KeyGen.init(128);

            SecretKey SecKey=KeyGen.generateKey();

            Cipher AesCipher=Cipher.getInstance("AES");
            AesCipher.init(Cipher.ENCRYPT_MODE,SecKey);

            byte[] byteText="My name is yogesh".getBytes();
            byte[] byteCipherText=AesCipher.doFinal(byteText);
            String cipherText = null;

            try {
                FileWriter fw=new FileWriter(FileName);
                BufferedWriter bw=new BufferedWriter(fw);
                bw.write(byteCipherText.toString());
                bw.close();
            }catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            try {
                FileReader fr=new FileReader(FileName);
                BufferedReader br=new BufferedReader(fr);
                cipherText=br.readLine();
                br.close();
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            AesCipher.init(Cipher.DECRYPT_MODE,SecKey);
            while(((cipherText.getBytes().length)%16)!=0)
            {
                cipherText=cipherText+pad;


            }

            byte[] bytePlainText=AesCipher.doFinal(cipherText.getBytes());
            FileWriter fw1;
            try {
                fw1 = new FileWriter(FileName2);
                BufferedWriter bw1=new BufferedWriter(fw1);
                bw1.write(bytePlainText.toString());
                bw1.close();

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }






}
like image 933
Yogesh D Avatar asked Dec 27 '13 06:12

Yogesh D


People also ask

What is Java AES encryption and decryption?

AES, Advanced Encryption Standard is a block ciphertext encryption and decryption algorithm that processes a block of 128 bits of data using secret keys of 128, 192, or 256 bits. We will also discuss how this algorithm can be implemented using the Java programming language.

Which algorithm is best for encryption and decryption in Java?

AES is an Advanced Encryption Standard algorithm. It is a type of symmetric, block cipher encryption and decryption algorithm. It works with key size 128, 192, and 256 bits. It uses a valid and similar secret key for both encryption and decryption.


2 Answers

You need to define what padding algorithm you use when you create instance of Cipher. Personally I use PKCS5.

So you should change:

Cipher AesCipher=Cipher.getInstance("AES");

to:

Cipher AesCipher=Cipher.getInstance("AES/CBC/PKCS5Padding");

CBC stands for Cipher-block chaining.

CBC requires IV to be passed. So you want to generate random IV and pass it in init method:

byte[] iv = new byte[16];
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
AesCipher.init(Cipher.ENCRYPT_MODE, SecKey, ivParameterSpec);

Note: it's a good practice to avoid magical numbers/strings in your code. I'd suggest to extract argument passes in Cipher#getInstance to a constant.

like image 197
Leri Avatar answered Sep 27 '22 19:09

Leri


Here, what you have to understand is that cipher text may contain non-printable characters. So, when you use readLine(), it will likely not give you all of the bytes in the file.

Also, byteCipherText.toString() does not give you what you thought you would get. In java, the toString() method does not give the string representation of the contents of the array.

There is no need to add padding to encrypted text. It is already padded.

import java.nio.file.Files;
import java.nio.file.Paths;
import javax.crypto.*;

public class Main {

    public static void main(String[] args) throws Exception {
        String fileName = "encryptedtext.txt";
        String fileName2 = "decryptedtext.txt";

        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(128);

        SecretKey secKey = keyGen.generateKey();

        Cipher aesCipher = Cipher.getInstance("AES");


        byte[] byteText = "Your Plain Text Here".getBytes();

        aesCipher.init(Cipher.ENCRYPT_MODE, secKey);
        byte[] byteCipherText = aesCipher.doFinal(byteText);
        Files.write(Paths.get(fileName), byteCipherText);


        byte[] cipherText = Files.readAllBytes(Paths.get(fileName));

        aesCipher.init(Cipher.DECRYPT_MODE, secKey);
        byte[] bytePlainText = aesCipher.doFinal(cipherText);
        Files.write(Paths.get(fileName2), bytePlainText);
    }
}
like image 31
Buddhima Gamlath Avatar answered Sep 27 '22 20:09

Buddhima Gamlath