Android中的gcm密码模式

时间:2018-10-04 00:29:58

标签: java android aes-gcm

我使用AES GCM密码模式加密,代码在Java中运行没有问题,但是在android异常错误出现

  

W / System.err:java.security.InvalidAlgorithmParameterException:   参数类型未知。 W / System.err:位于   com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineInit(BaseBlockCipher.java:559)           在javax.crypto.Cipher.init(Cipher.java:616)           在javax.crypto.Cipher.init(Cipher.java:566)           在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模拟器=> Genymotion“自定义电话4.4.4 API 19”

1 个答案:

答案 0 :(得分:0)

在Android API 19上,尽管平台添加了GCMParameterSpec类,但内置密码不支持该类,因此您会看到“未知参数类型”异常。

要解决此问题,请使用类似于以下代码的规范生成规范:

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

此外,您可能还会发现updateAADjava.lang.UnsupportedOperationException: This cipher does not support Authenticated Encryption with Additional Data的呼叫失败。同样,尽管该功能是在API 19中添加的,但似乎也不支持该功能。最好的建议是仅在updateAAD及更高版本上运行时才调用Build.VERSION_CODES.LOLLIPOP