2

I use AES GCM cipher mode encryption, the code run without any problem in java but, at android exception error appears

W/System.err: java.security.InvalidAlgorithmParameterException: unknown parameter type. W/System.err: at com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineInit(BaseBlockCipher.java:559) at javax.crypto.Cipher.init(Cipher.java:616) at javax.crypto.Cipher.init(Cipher.java:566) at algorithm.encryption.AESencryption.gcmMode(AESencryption.java:71)

public static byte[] gcmMode(int gcmCipherMode, byte[] aadHeader,char[] password, byte[] inputBytes) {
    byte[] outputBytes = new byte[0];
    byte[] salt;
    byte[] iv;
    byte[] res;
    SecretKeySpec ks;
    try {
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        Cipher c = Cipher.getInstance("AES/GCM/NoPadding");
        iv = new byte[12]; random.nextBytes(iv);
        GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(128, iv);
        switch (gcmCipherMode) {
            case Cipher.ENCRYPT_MODE:
                salt = new byte[16]; random.nextBytes(salt);
                res = salt(password, salt);
                ks = new SecretKeySpec(res, "AES");
                c.init(Cipher.ENCRYPT_MODE, ks, gcmParameterSpec);
                c.updateAAD(aadHeader);
                outputBytes = arrayByteConcatenate(salt, iv);
                outputBytes = arrayByteConcatenate(outputBytes, c.doFinal(inputBytes));
                break;
            case Cipher.DECRYPT_MODE:
                if (inputBytes.length > 44) {
                    // salt = Arrays.copyOfRange(os, 0, 16);
                    salt = arrayByteSplit(inputBytes, 0, 16);
                    // iv = Arrays.copyOfRange(os, 16, 28);
                    iv = arrayByteSplit(inputBytes, 16, 28);
                    // byte[] es = Arrays.copyOfRange(os, 28, os.length);
                    res = salt(password, salt);
                    ks = new SecretKeySpec(res, "AES");
                    c.init(Cipher.DECRYPT_MODE, ks, gcmParameterSpec);
                    c.updateAAD(aadHeader);
                    // Return our Decrypted String
                    outputBytes = c.doFinal(arrayByteSplit(inputBytes, 28, inputBytes.length));
                }else{
                    System.out.println("Wrong cipher");
                }
                break;

            default:
                System.out.println("UnKnown");
                break;
        }


    } catch (NoSuchAlgorithmException | NoSuchPaddingException
            | InvalidKeyException | IllegalBlockSizeException
            | BadPaddingException | InvalidParameterException
            | InvalidAlgorithmParameterException e) {
        e.printStackTrace();
    }
    return outputBytes;
}

static byte[] salt (char[] password, byte[] salt) {
    SecretKeyFactory skf = null;
    byte[] res = new byte[0];
    try {
        skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        PBEKeySpec spec = new PBEKeySpec(password, salt, 100000, 128);
        SecretKey key = skf.generateSecret(spec);
        res = key.getEncoded();
    } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
        e.printStackTrace();
    }
    return res;
}   

compileSdkVersion 28

minSdkVersion 19

targetSdkVersion 28

Android emulator => Genymotion "custom phone 4.4.4 API 19 "

Hossein Golshani
  • 1,847
  • 5
  • 16
  • 27
Sherif Awad
  • 171
  • 2
  • 10
  • Hi! Have you ever found a solution to this issue? I'm finding myself running into the same issue. Thank you! – Markus A. Jul 13 '20 at 05:03

1 Answers1

1

On Android API 19, although the platform added the GCMParameterSpec class, the built-in ciphers do not support it, hence the "unknown parameter type" exception you are seeing.

To fix this, instead generate the spec with code similar to:

AlgorithmParameterSpec spec;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    spec = new GCMParameterSpec(128, iv);
} else {
    spec = new IvParameterSpec(iv);
}

Additionally you may also find your call to updateAAD fail with java.lang.UnsupportedOperationException: This cipher does not support Authenticated Encryption with Additional Data. Again, it seems that although the function was added in API 19 it is also not supported. The best advice is to only call updateAAD when running on Build.VERSION_CODES.LOLLIPOP and higher.

appmattus
  • 2,788
  • 25
  • 16