0

I am trying to write and encrypt/decrypt program that. I am able to encrypt the String just fine, but while decrypting, I am getting the above error.

My code currently looks like this:

import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

public class Trial {

    static String key = "USSWIF3925NJ50R";
    static String userName = "sam1234t";

    public static void main(String[] arg) throws IllegalBlockSizeException, BadPaddingException {

        Trial trial = new Trial();

        Cipher cipher = trial.initialiseCipher("encrypt");

        // Finally generate the transient key in bytes.
        byte[] transientKey = cipher.doFinal(userName.getBytes(StandardCharsets.UTF_8));

        String encryptedPassword = Base64.getEncoder().encodeToString(transientKey);

        System.out.println("Encrypted Key: " + encryptedPassword);

        cipher = trial.initialiseCipher("decrypt");

        // Finally decrypt the transient key in bytes.
        byte[] temp = cipher.doFinal(encryptedPassword.getBytes(StandardCharsets.UTF_8));
        String decryptedKey = new String(Base64.getDecoder().decode(temp));

        System.out.println("Decrypted Key: " + decryptedKey);
    }


    private Cipher initialiseCipher(String mode) {

        Cipher cipher = null;

        try {

            Security.setProperty("crypto.policy", "unlimited");

            SecureRandom secureRandom = new SecureRandom();
            byte[] salt = new byte[256];
            byte[] ivBytes = new byte[16];

            secureRandom.nextBytes(salt);
            secureRandom.nextBytes(ivBytes);

            // Generate the Key Specs.
            IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);
            PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(salt, 65536, ivParameterSpec);
            PBEKeySpec pbeKeySpec = new PBEKeySpec((key + userName).toCharArray());

            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBEWITHHMACSHA512ANDAES_256");
            SecretKey secretKey = secretKeyFactory.generateSecret(pbeKeySpec);

            cipher = Cipher.getInstance("PBEWITHHMACSHA512ANDAES_256");

            if (mode.equals("encrypt")) {
                cipher.init(Cipher.ENCRYPT_MODE, secretKey, pbeParameterSpec);
            } else if (mode.equals("decrypt")) {
                cipher.init(Cipher.DECRYPT_MODE, secretKey, pbeParameterSpec);
            }

        } catch (NoSuchAlgorithmException e) {

            e.printStackTrace();

        } catch (InvalidKeySpecException e) {

            e.printStackTrace();

        } catch (NoSuchPaddingException e) {

            e.printStackTrace();

        } catch (InvalidKeyException e) {

            e.printStackTrace();

        } catch (InvalidAlgorithmParameterException e) {

            e.printStackTrace();
        }

        return cipher;
    }
}

When I run the piece of code I get the output:

Encrypted Key: 9DfMJ/yuEFobrdGVsVkhpQ==
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.prepareInputBuffer(CipherCore.java:1005)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:848)
    at com.sun.crypto.provider.PBES2Core.engineDoFinal(PBES2Core.java:323)
    at javax.crypto.Cipher.doFinal(Cipher.java:2164)
    at com.att.logicalprovisioning.simulators.Trial.main(Trial.java:43)

All the solutions I Googled for use the Cipher algorithm as AES. So I am not sure it replicates like for like, I have tried a few of them, without any luck.

Any help would be helpful. Thanks.

hell_storm2004
  • 1,401
  • 2
  • 33
  • 66
  • 2
    You have to Base64 decode the ciphertext before decryption and UTF-8 decode the decrypted data (and not vice versa). – Topaco Dec 14 '22 at 14:16
  • ...and during decryption salt and IV from encryption must be used. – Topaco Dec 14 '22 at 14:21
  • @Topaco Are you trying to say I make `salt` and `ivBytes` as statics at the top? – hell_storm2004 Dec 14 '22 at 14:29
  • 3
    No, absolutely not. Static values are insecure. IV and salt are to be generated randomly during encryption (as you do). However, after encryption they are concatenated with the ciphertext, e.g. salt|iv|ciphertext, and this is sent to the decrypting side (note that salt and IV are not secret). The decrypting side separates the 3 parts and thus has everything needed for decryption. – Topaco Dec 14 '22 at 14:37
  • Just in general you have to apply de-transformations in the reverse order of the transformations, so in this case it should be plaintext -> encrypt -> base64 encode -> transmit -> receive -> base-64 decode -> decrypt -> plaintext again. – President James K. Polk Dec 14 '22 at 16:43

0 Answers0