Search code examples
javaexceptionencryptioncryptographyillegalargumentexception

java.lang.IllegalArgumentException: Empty key


 public byte[] encryptWithAesKey(byte[] key, byte[] iv, byte[] data) {
      try {
             IvParameterSpec ivSpec = new IvParameterSpec(iv);
             Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
             SecretKeySpec aesKey = new SecretKeySpec(key, "AES");
             cipher.init(Cipher.ENCRYPT_MODE, aesKey, ivSpec);
             return cipher.doFinal(data);
          } catch (Exception e) {
             System.out.println("Error while encrypting: " + e.toString());
          }
     return null;
 }

at javax.crypto.spec.SecretKeySpec.(SecretKeySpec.java:96)

This is returning an exception but works well in android 28 lower.

StackTrace as follows:

System.out: encryptwithAES:[B@b8979fbIV:[B@78d7813data:[B@3841a50
System.err: java.lang.IllegalArgumentException: Empty key
System.err:    at javax.crypto.spec.SecretKeySpec.<init>(SecretKeySpec.java:96)
System.err:    at com..Security.SecurityController.encryptWithAesKey(SecurityController.java:93)
System.err:    at com..Controllers.Files.FileController.encryptAndSaveFile(FileController.java:75)
System.err:    at com..Controllers.Files.FileControllerRN.encryptAndSaveFileRN(FileControllerRN.java:68)
System.err:    at java.lang.reflect.Method.invoke(Native Method)
System.err:    at com.facebook.react.bridge.JavaMethodWrapper.invoke(JavaMethodWrapper.java:372)
System.err:    at com.facebook.react.bridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:151)
System.err:    at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method)
System.err:    at android.os.Handler.handleCallback(Handler.java:883)
System.err:    at android.os.Handler.dispatchMessage(Handler.java:100)
System.err:    at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:27)
System.err:    at android.os.Looper.loop(Looper.java:214)
System.err:    at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(MessageQueueThreadImpl.java:226)
System.err:    at java.lang.Thread.run(Thread.java:919)

Solution

  • This (or similar) is the code that is throwing the exception:

    public SecretKeySpec(byte[] key, String algorithm) {
        if (key == null || algorithm == null) {
            throw new IllegalArgumentException("Missing argument");
        }
        if (key.length == 0) {
            throw new IllegalArgumentException("Empty key");
        }
        this.key = key.clone();
        this.algorithm = algorithm;
    }
    

    Notice that the exception is thrown when the key array has zero length. Indeed, this is the only situation where a SecretKeySpec constructor will throw this exception with this message1. So there no room for any doubt that this is what your code is doing.

    Solution: fix the code that is calling your encryptWithAesKey so that it doesn't pass in a zero length byte array.


    1 - This applies to the Sun / Oracle / OpenJDK codebase. The Android implementation of SecretKeySpec constructor that I found uses a different message for this: "key.length == 0". It appears that in newer versions of Android they must have changed the behavior to be more Java(tm) compliant. Or alternatively, somehow your Android platform is using an OpenJDK-based crypto implementation.


    byte[] key is [B@b8979fb, I checked it.

    That doesn't prove that the byte array is not zero length. Please read this: Why do I get garbage values when print arrays in Java?

    In short, the [B@b8979fb tells you that it is a non-null byte array, but absolutely nothing about its length or content.

    This is returning an exception but works well in Android 28 lower.

    In the Android case you must be supplying a non-empty byte array. The Android version will also fail (same exception, different message) if you supply an empty byte array as the key.