-2

Hi I'm trying to create an encrypt/decrypt app in java for a project and I managed to do the encrypt decrypt in the same class however I need two separate classes one for encrypt and one for decrypt, but I've been getting this error (Instead of printing the message I initially encrypted) and I'm not sure what I need to do to make it work.

Without separating the code into classes:-

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import java.util.Scanner;

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 Encrypt1
{    
public static void main(String[] argv) {

    try{

        //KeyGenerator keygenerator = KeyGenerator.getInstance("AES");

        //SecretKey myAesKey = keygenerator.generateKey(key);

        Scanner input = new Scanner(System.in);

        System.out.println("Please enter a message you'd like to encrypt");
        String plaintext = input.nextLine();

        System.out.println("Please enter a 16 digit password: ");
        String pass = input.nextLine();

        byte[] key = pass.getBytes();
        SecretKeySpec aesKey = new SecretKeySpec(key, "AES");

        Cipher aesCipher;

        // Create the cipher 
        aesCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");

        // Initialize the cipher for encryption
        aesCipher.init(Cipher.ENCRYPT_MODE, aesKey);

        //sensitive information
        byte[] text = plaintext.getBytes();

        System.out.println("Text [Byte Format] : " + text);
        System.out.println("Text : " + new String(text));

        // Encrypt the text
        byte[] textEncrypted = aesCipher.doFinal(text);

        System.out.println("Text Encryted : " + textEncrypted);

        // Initialize the same cipher for decryption
        aesCipher.init(Cipher.DECRYPT_MODE, aesKey);

        // Decrypt the text
        byte[] textDecrypted = aesCipher.doFinal(textEncrypted);

        System.out.println("Text Decryted : " + new String(textDecrypted));

    }catch(NoSuchAlgorithmException e){
        e.printStackTrace();
    }catch(NoSuchPaddingException e){
        e.printStackTrace();
    }catch(InvalidKeyException e){
        e.printStackTrace();
    }catch(IllegalBlockSizeException e){
        e.printStackTrace();
    }catch(BadPaddingException e){
        e.printStackTrace();
    } 

}
}

Attempt to separate it into classes:-

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Scanner;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;


public class Encrypt2 {

public static void main(String[] args) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException {
    // TODO Auto-generated method stub

    Encrypt();
    Decrypt();

}


public static void Encrypt() throws IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException{

    Scanner input = new Scanner(System.in);

    System.out.println("Please enter a message you'd like to encrypt");
    String plaintext = input.nextLine();

    System.out.println("Please enter a 16 digit password: ");
    String pass = input.nextLine();

    byte[] key = pass.getBytes();
    SecretKeySpec aesKey = new SecretKeySpec(key, "AES");

    Cipher aesCipher;

    // Create the cipher 
    aesCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");

    // Initialize the cipher for encryption
    aesCipher.init(Cipher.ENCRYPT_MODE, aesKey);

    //sensitive information
    byte[] text = plaintext.getBytes();

    System.out.println("Text [Byte Format] : " + text);
    System.out.println("Text : " + new String(text));

    // Encrypt the text
    byte[] textEncrypted = aesCipher.doFinal(text);

    System.out.println("Text Encryted : " + textEncrypted);

}
public static void Decrypt() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{

     Scanner input = new Scanner(System.in);

     System.out.println("Please enter a message you'd like to decrypt");
        String ciphertext = input.nextLine();
        byte[] textEncrypted = ciphertext.getBytes();


        System.out.println("Please enter a 16 digit password: ");
        String passw = input.nextLine();


        byte[] key = passw.getBytes();
        SecretKeySpec aesKey = new SecretKeySpec(key, "AES");

        Cipher aesCipher;

        // Create the cipher 
        aesCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        String pass = input.nextLine(); // Initialize the same cipher for decryption
        aesCipher.init(Cipher.DECRYPT_MODE, aesKey);

        // Decrypt the text
        byte[] textDecrypted = aesCipher.doFinal(textEncrypted);

        System.out.println("Text Decryted : " + new String(textDecrypted));
}
}

Btw I have type a 16 bit character and everything as well, here is the result I got from running the code:-

Please enter a message you'd like to encrypt
hi
Please enter a 16 digit password: 
1234567890987654
Text [Byte Format] : [B@382ce255
Text : hi
Text Encryted : [B@1b523bd4
Please enter a message you'd like to decrypt
[B@1b523bd4
Please enter a 16 digit password: 
1234567890987654
Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:750)
    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 Encrypt2.Decrypt(Encrypt2.java:80)
    at Encrypt2.main(Encrypt2.java:18)

here is a screenshot of the result if needed: http://puu.sh/dnITY/eac9faa84f.png

Artjom B.
  • 61,146
  • 24
  • 125
  • 222

1 Answers1

1

Problem

As njzk2 points out in the comments, printing an array in Java doesn't print the contents of the array, but only some meta data to identify the object by during the execution. It is not the encrypted data that you're printing there.

Specifically it is Object.toString()

getClass().getName() + '@' + Integer.toHexString(hashCode())

because Array objects don't have their own toString method.

Solution

You need to encode the byte[] to a String before printing it. Altough you could use Arrays.toString(textEncrypted), but there are better ways.

You could encode the textEncrypted as Base64 before showing it to the user, so that it can be "copied". See this question for example code: Base 64 encode and decode example code

In the decryption method, you should then decode the String to byte[] before giving to doFinal.

Community
  • 1
  • 1
Artjom B.
  • 61,146
  • 24
  • 125
  • 222
  • You shouldn't use `ECB`. `CBC` is better, but then you let the user "copy" the ciphertext, so I don't know if you're at least concerned about the security of the system you're building. – Artjom B. Dec 09 '14 at 18:11
  • Where can I get the jar files so I cane use base 64? – Manvir Speedy Singh Dhinse Dec 09 '14 at 18:43
  • `toString()` on a byte array results in a call to [`Object.toString()`](https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#toString()). [B is just the "class name" of a byte[], [ for array, B for byte of course. However [`Object.hashCode()`](https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode()) may return a memory location or similar. – Maarten Bodewes Dec 09 '14 at 18:48
  • @ManvirSpeedySinghDhinse You probably don't need another jar. Android [has it](https://developer.android.com/reference/android/util/Base64.html) since API level 8 and Java has a native version since 8 (1.8). – Artjom B. Dec 09 '14 at 18:49