我使用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”
答案 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);
}
此外,您可能还会发现updateAAD
对java.lang.UnsupportedOperationException: This cipher does not support Authenticated Encryption with Additional Data
的呼叫失败。同样,尽管该功能是在API 19中添加的,但似乎也不支持该功能。最好的建议是仅在updateAAD
及更高版本上运行时才调用Build.VERSION_CODES.LOLLIPOP
。