我谷歌搜索和测试解决方案一段时间,到目前为止没有成功。它总是存在一些问题。以下代码是"工作" (在Android Kitkat及更高版本中,意味着在运行时不显示任何错误),但解密文件不可读。为什么呢?
final static byte[] iv = new byte[16];//ADDED
final static int buffer = 102400;
final static String encryptionType = "AES/CFB8/NoPadding";//CHANGED TO DIFFERENT TYPE
static void encrypt(String password, File fileInput, File fileOutput) throws Exception {
IvParameterSpec ivParams = new IvParameterSpec(iv);//ADDED
FileInputStream fis = new FileInputStream(fileInput);
FileOutputStream fos = new FileOutputStream(fileOutput);
SecretKeySpec sks = new SecretKeySpec(password.getBytes("UTF-8"), encryptionType);
Cipher cipher = Cipher.getInstance(encryptionType);
//cipher.init(Cipher.ENCRYPT_MODE, sks);REPLACED
cipher.init(Cipher.ENCRYPT_MODE, sks, ivParams);
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
int b;
byte[] d = new byte[buffer];
while ((b = fis.read(d)) != -1) {
cos.write(d, 0, b);
}
cos.flush();
cos.close();
fis.close();
}
static void decrypt(String password, File fileInput, File fileOutput) throws Exception {
IvParameterSpec ivParams = new IvParameterSpec(iv);//ADDED
FileInputStream fis = new FileInputStream(fileInput);
FileOutputStream fos = new FileOutputStream(fileOutput);
SecretKeySpec sks = new SecretKeySpec(password.getBytes("UTF-8"), encryptionType);
Cipher cipher = Cipher.getInstance(encryptionType);
//cipher.init(Cipher.ENCRYPT_MODE, sks);REPLACED
cipher.init(Cipher.DECRYPT_MODE, sks, ivParams);
CipherInputStream cis = new CipherInputStream(fis, cipher);
int b;
byte[] d = new byte[buffer];
while ((b = cis.read(d)) != -1) {
fos.write(d, 0, b);
}
fos.flush();
fos.close();
cis.close();
}
编辑:在我将类型更改为" AES / CFB8 / NoPadding"后,似乎没问题,过程中没有错误,但解密文件无法读取。
答案 0 :(得分:1)
解密方法中的问题是由以下行引起的:
cipher.init(Cipher.ENCRYPT_MODE, sks);
模式需要Cipher.DECRYPT_MODE
,因此该行应为
cipher.init(Cipher.DECRYPT_MODE, sks);
其他问题是长期过时的DESede算法的使用,缺乏任何IV生成和处理,没有良好的基于密码的密钥派生算法,以及密文上缺少任何MAC。正确使用AES GCM模式以及正确的随机数生成和处理,以及使用PBKDF2(可在Android和Oracle Java上使用)将代表重大改进。
您没有提供IV,因此会自动生成一个IV。您必须找到将此IV传输给收件人的方法。通常,IV / Nonce前置于密文并由接收者剥离以便解密数据。 CipherInputStream / CipherOutputStream不会为您执行此操作,因此您必须自己执行此操作。
答案 1 :(得分:0)
我终于通过使用更短的密码解决了这个问题。我不知道为什么,但在Android 7和8上,长密码没有问题,但Android 4.4上的相同密码会导致疯狂的错误和制动加密。