amirkamizi
amirkamizi

Reputation: 142

Problem with java Cipher when i want to decipher it

I have made an app with javafx that I can write something and save it to database. my database is sqlite. it's a very simple app. although I've added login app to my writing app, still the sqlite can be opened by any software. instead of encrypting the sqlite db(which i didn't know and i found really confusing to do :) ) I decided to encrypt the text in java and later when i want to read it i would turn it back to normal and show it.

I learned how to do it from this link and i changed it to print the string instead of writing to a file so my final code looks like this:

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

    String textA = "";
    String textB="";

    byte[] thisismykey = "Hello How manyBytes are in@hts A".getBytes();
    SecretKey secKey = new SecretKeySpec(thisismykey, "AES");


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

    //turn your original text to byte
    byte[] myoriginaltexttobyte = "Your Plain Text Here".getBytes();
    //activate the encrypt method
    aesCipher.init(Cipher.ENCRYPT_MODE, secKey);
    //encrypt the text and assign the encrypted text to a byte array
    byte[] bytecipheredoforgtext = aesCipher.doFinal(myoriginaltexttobyte);
    //change it to string with new string
    textA = new String(bytecipheredoforgtext);
    System.out.println(textA);

    //get the bytes of encrypted text and assign it to a byte array
    byte[] byteofencryptedtext = textA.getBytes();
    //activate the decrypt mode of the cipher
    aesCipher.init(Cipher.DECRYPT_MODE, secKey);
    //decrypt the encrypted text and assign it to a byte array
    byte[] byteofencryptedbacktonormaltext = aesCipher.doFinal(byteofencryptedtext);
    //change it to string with new string
    textB = new String(byteofencryptedbacktonormaltext);
    System.out.println(textB);
}

now that encrypt and decrypt are at the same method it works perfectly but I want to change it to a class with different methods so i could encrypt a text with one method and decrypt it with another. but when i separate things decrypt doesn't work well. Encrypt work well. this is the code now:

public class CipherFinalB {

//from https://stackoverflow.com/questions/20796042/aes-encryption-and-decryption-with-java/20796446#20796446
private final byte[] thisismykey;
private final SecretKey secKey;
private final Cipher aesCipher;
public CipherFinalB() throws NoSuchPaddingException, NoSuchAlgorithmException {
    thisismykey = "HellodHowfmanyBytesgarehin@htseA".getBytes();
    secKey = new SecretKeySpec(thisismykey, "AES");

    aesCipher = Cipher.getInstance("AES");

}public String encrypt (String originaltext) throws InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
    byte[] myoriginaltexttobyte =originaltext.getBytes();
    aesCipher.init(Cipher.ENCRYPT_MODE, secKey);
    byte[] bytecipheredoforgtext = aesCipher.doFinal(myoriginaltexttobyte);
    String textA = new String(bytecipheredoforgtext);
    System.out.println(textA);
    return new String(bytecipheredoforgtext);
}

public String decrypt (String encryptedtext) throws InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
    byte[] byteofencryptedtext = encryptedtext.getBytes();
    aesCipher.init(Cipher.DECRYPT_MODE, secKey);
    byte[] byteofencryptedbacktonormaltext = aesCipher.doFinal(byteofencryptedtext);
    return new String(byteofencryptedbacktonormaltext);
}

}

when i use the encrypt method it gives me back a string. and when i send the same string to decrypt method it doesn't work and gives me the following error:

Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:936)
    at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:847)
    at java.base/com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
    at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2191)
    at main.CipherFinalB.decrypt(CipherFinalB.java:66)
    at main.CipherTest.main(CipherTest.java:16)

What should i do?

UPDATE ANSWER:

as @Juan said the problem was "when data is ciphered you may have any byte in the array, not only printable characters." So I changed the method to return byte for encrypt method and decrypt method. decrypt method now gets byte as parameter instead of string and now everything works fine.

the updated code looks like this:

 public byte[] encrypt (String originaltext) throws InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
    byte[] myoriginaltexttobyte =originaltext.getBytes();
    aesCipher.init(Cipher.ENCRYPT_MODE, secKey);
    byte[] bytecipheredoforgtext = aesCipher.doFinal(myoriginaltexttobyte);
    String textA = new String(bytecipheredoforgtext);
    System.out.println(textA);
    return bytecipheredoforgtext;
}

public byte[] decrypt (byte[] encryptedtext) throws InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
    byte[] byteofencryptedtext = encryptedtext;
    aesCipher.init(Cipher.DECRYPT_MODE, secKey);
    byte[] byteofencryptedbacktonormaltext = aesCipher.doFinal(byteofencryptedtext);
    return byteofencryptedbacktonormaltext;
}

Upvotes: 0

Views: 878

Answers (1)

Juan
Juan

Reputation: 5589

I am not sure that the error is caused by this but the conversion between String and byte[] you are doing may work with bytes in the character set range, but when data is ciphered you may have any byte in the array, not only printable characters.

After you get the byte[] with the cyphered text, encode it as Base64 and store the string representation.

When decrypting, first decode the Base64 into the byte[] and then decipher it.

See Base64 class

Upvotes: 1

Related Questions