我正在尝试使用AES算法和GCM模式对字符串进行加密和解密。
我的代码能够加密字符串,但无法解密编码的数据。
遵循的步骤:
Create Key()
Encrypt(file with IV)
Decryptfile(encoded data);
失败
java.io.IOException:javax.crypto.AEADBadTagException
请帮助。
@RequiresApi(api = Build.VERSION_CODES.M)
private static void encrypt(Context context,String content, String fileName,Cipher cipher1) throws Exception {
final KeyGenerator keyGenerator = KeyGenerator
.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
final KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder("TK",
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setRandomizedEncryptionRequired(false)
.build();
keyGenerator.init(keyGenParameterSpec);
final SecretKey secretKey= keyGenerator.generateKey();
final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
byte[] iv = new byte[GCM_IV_LENGTH];
(new SecureRandom()).nextBytes(iv);
GCMParameterSpec ivSpec = new GCMParameterSpec(GCM_TAG_LENGTH * Byte.SIZE, iv);
cipher.init(Cipher.ENCRYPT_MODE, secretKey,ivSpec);
try (FileOutputStream fileOut = context.openFileOutput(fileName, Context.MODE_PRIVATE);
CipherOutputStream cipherOut = new CipherOutputStream(fileOut, cipher)) {
cipherOut.write(iv);
cipherOut.write(content.getBytes("UTF-8"));
cipherOut.flush();
}
}
@RequiresApi(api = Build.VERSION_CODES.M)
private static String decrypt(Context context,String fileName) throws Exception{
String content;
try (FileInputStream fileIn = context.openFileInput(fileName)) {
byte[] fileIv = new byte[12];
fileIn.read(fileIv);
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
final KeyStore.SecretKeyEntry secretKeyEntry = (KeyStore.SecretKeyEntry) keyStore
.getEntry("TK", null);
final SecretKey secretKey = secretKeyEntry.getSecretKey();
final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
final GCMParameterSpec spec = new GCMParameterSpec(128, fileIv);
cipher.init(Cipher.DECRYPT_MODE, secretKey, spec);
try (
CipherInputStream cipherIn = new CipherInputStream(fileIn, cipher);
InputStreamReader inputReader = new InputStreamReader(cipherIn);
BufferedReader reader = new BufferedReader(inputReader)
) {
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
content = sb.toString();
}
}
return content;
}
例外:
java.io.IOException: javax.crypto.AEADBadTagException
at javax.crypto.CipherInputStream.getMoreData(CipherInputStream.java:133)
at javax.crypto.CipherInputStream.read(CipherInputStream.java:249)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:288)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:351)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:180)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:172)
at java.io.BufferedReader.readLine(BufferedReader.java:335)
at java.io.BufferedReader.readLine(BufferedReader.java:400)
答案 0 :(得分:0)
发现了问题。
问题是因为代码还对IV进行了加密以启动文件,相反,它应该直接加密到文件输出流而不是密码输出流。
private static void encrypt(Context context,String content, String fileName,Cipher cipher1) throws Exception {
...
try (FileOutputStream fileOut = context.openFileOutput(fileName, Context.MODE_PRIVATE);
CipherOutputStream cipherOut = new CipherOutputStream(fileOut, cipher)) {
fileOut.write(iv); // change is here
cipherOut.write(content.getBytes("UTF-8"));
cipherOut.flush();
}