1

I am trying to encrypt a simple test "sometext" using "AES/GCM/NoPadding".
I have a main method in which I am first passing a string as an argument that is supposed to get encrypted. The encrypted text will appear on the console. Then following that decryption gets called (by passing the encrypted text) to check if the decryption is working fine, i.e. if I am getting back the same text after decryption. I am calling the main class, and its failing in my getCipher() custom method with the exception:

Exception in thread "main" my.package.EncryptionException: java.security.InvalidKeyException: Illegal key size
        at my.package.Encryptor.encrypt(Encryptor.java:76)
        at my.package.Encryptor.encrypt(Encryptor.java:61)
        at my.package.Encryptor.main(Encryptor.java:151)
Caused by: java.security.InvalidKeyException: Illegal key size
        at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1039)
        at javax.crypto.Cipher.implInit(Cipher.java:805)
        at javax.crypto.Cipher.chooseProvider(Cipher.java:864)
        at javax.crypto.Cipher.init(Cipher.java:1396)
        at javax.crypto.Cipher.init(Cipher.java:1327)
        at my.package.Encryptor.getCipher(Encryptor.java:134)
        at my.package.Encryptor.encrypt(Encryptor.java:69)
        ... 2 more

I am not sure why is this Illegal key size giving error. I have my key "SecREtKeY" within 16 chars.
Here is the code below:

public class Encryptor {

    private static final String ALGORITHM_AES256 = "AES/GCM/NoPadding";
    private static final int IV_LEN = 16;
    private static final int KEY_LEN = 32;
    private final SecureRandom random;
    private final byte[] inputKey;
    private final SecretKeySpec secretKeySpec;
    private final Cipher cipher;

    Encryptor() throws EncryptionException 
    {
        String secretKey = "SecREtKeY";
        byte[] key = secretKey.getBytes(StandardCharsets.UTF_8);
        if (key == null) {
            throw new EncryptionException("Null Key");
        }

        inputKey = new byte[key.length];
        System.arraycopy(key, 0, inputKey, 0, inputKey.length);

        byte[] aesKey = trimKey(key);
        System.out.println("aesKey.length: "+aesKey.length);

        try
        {
            random = SecureRandom.getInstance("SHA1PRNG");
            this.secretKeySpec = new SecretKeySpec(aesKey, "AES");
            this.cipher = Cipher.getInstance(ALGORITHM_AES256);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            throw new EncryptionException(e);
        }
    }

    /*
     * Encrypts plaint text. Returns Encrypted String.
     */
    String encrypt(String plaintext) throws EncryptionException
    {
        return encrypt(plaintext.getBytes(StandardCharsets.UTF_8));
    }

    String encrypt(byte[] plaintext) throws EncryptionException
    {
        try 
        {
            byte[] iv = getRandom(IV_LEN);
            Cipher msgcipher = getCipher(Cipher.ENCRYPT_MODE, iv);
            byte[] encryptedTextBytes = msgcipher.doFinal(plaintext);
            byte[] payload = concat(iv, encryptedTextBytes);

            return Base64.getEncoder().encodeToString(payload);
        } 
        catch (BadPaddingException | InvalidKeyException | IllegalBlockSizeException | InvalidAlgorithmParameterException e){
            throw new EncryptionException(e);
        }
    }

    /*
     * Decrypts plaint text. Returns decrypted String.
     */
    String decrypt(String ciphertext) throws EncryptionException 
    {
        return decrypt(Base64.getDecoder().decode(ciphertext));
    }

    String decrypt(byte[] cipherBytes) throws EncryptionException 
    {
        byte[] iv = Arrays.copyOf(cipherBytes, IV_LEN);

        byte[] cipherText = Arrays.copyOfRange(cipherBytes, IV_LEN, cipherBytes.length);
        try {
            Cipher cipher = getCipher(Cipher.DECRYPT_MODE, iv);
            byte[] decrypt = cipher.doFinal(cipherText);
            return new String(decrypt, StandardCharsets.UTF_8);
        } catch (BadPaddingException | InvalidKeyException | IllegalBlockSizeException | InvalidAlgorithmParameterException e) {
            throw new EncryptionException(e);
        }
    }


    private byte[] trimKey(byte[] key)
    {
        byte[] outkey = new byte[KEY_LEN];

        if(key.length >= KEY_LEN) {
            System.arraycopy(key, key.length - KEY_LEN, outkey, 0, KEY_LEN);
        } 
        else {
            System.arraycopy(key, 0, outkey, 0, key.length);
        }

        return outkey;
    }

    private byte[] getRandom(int size) 
    {
        byte[] data = new byte[size];
        random.nextBytes(data);
        return data;
    }

    private byte[] concat(byte[] first, byte[] second) 
    {
        byte[] result = Arrays.copyOf(first, first.length + second.length);
        System.arraycopy(second, 0, result, first.length, second.length);
        return result;
    }

    private Cipher getCipher(int encryptMode, byte[] iv) throws InvalidKeyException, InvalidAlgorithmParameterException 
    {
        GCMParameterSpec gcmSpec = new GCMParameterSpec(IV_LEN * 8, iv);
        cipher.init(encryptMode, getSecretKeySpec(), gcmSpec);
        return cipher;
    }

    private SecretKeySpec getSecretKeySpec() {
        return secretKeySpec;
    }



    public static void main(String[] args) throws Exception 
    {
        if(args.length == 1) {
            String plainText = args[0];

            Encryptor aes = new Encryptor();

            String encryptedString = aes.encrypt(plainText);
            System.out.println(plainText + ":" + encryptedString);

            String decryptedString = aes.decrypt(encryptedString);
            System.out.println(encryptedString+":"+decryptedString);
        } 
        else {
            System.out.println("USAGE: java my.package.Encryptor [text to encrypt]");
        }
    }
}  

Any idea why am i getting this error ?

5
  • Note the key size is 16-bytes secretKey = "SecREtKeY" but specified as KEY_LEN = 32: they don't match. Also see the answer by @Jens and note that 128-bit AES is essentially as secure as 256-bit, neither can be brute forced unless the key is weak and then both have the same vulnerability. Commented Mar 13, 2018 at 12:33
  • so should I make KEY_LEN = 16 ? Commented Mar 13, 2018 at 12:46
  • You should make KEY_LEN the same as the size of the actual key. With a key size of 16-bytes there is no need to install the Java Cryptography Extension. Commented Mar 13, 2018 at 12:49
  • I made the KEY_LEN = secretKey.length();. But now I am getting the exception Invalid AES key length: 9 bytes Caused by: java.security.InvalidKeyException: Invalid AES key length: 9 bytes at com.sun.crypto.provider.AESCipher.engineGetKeySize(AESCipher.java:509) Commented Mar 13, 2018 at 12:58
  • 1
    Use a debugger! Your trimKey() function isn't returning a properly sized key, it's just copying the key you pass in. Commented Mar 13, 2018 at 13:11

1 Answer 1

1

java.security.InvalidKeyException: Illegal key size indicates that you have not installed the JCE (Java Cryptography Extension). It is needed for AES256

For Java 8 you can download it here: http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks alot @Jens...that was the problem :D. Thanks a tons :D :D

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.