在 Android 应用程序(API 级别 30)上,我有这个 Hava 函数,可以解密
InputStream
(基本上是一个 zip 文件):
public static byte[] decryptStreamWithEmbeddedHash(InputStream inputStream, String password) throws Exception {
String customSalt = "myPrivateCustomSalt";
int iterations = 10000;
byte[] salt = (password + customSalt).getBytes(StandardCharsets.US_ASCII);
// derive key and IV via PBKDF2/HMAC/SHA256
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterations, 256 + 128);
byte[] keyIv = factory.generateSecret(spec).getEncoded();
ByteBuffer keyIvBuffer = ByteBuffer.wrap(keyIv);
byte[] key = new byte[32];
keyIvBuffer.get(key);
SecretKey secret = new SecretKeySpec(key, "AES");
byte[] iv = new byte[16];
keyIvBuffer.get(iv);
// read hash length
byte[] hashLengthBytes = new byte[4]; // sizeof(int)
if (inputStream.read(hashLengthBytes, 0, 4) == -1) {
throw new Exception("stream empty");
}
int hashLength = ByteBuffer.wrap(hashLengthBytes).order(ByteOrder.LITTLE_ENDIAN).getInt();
// read hash
byte[] embeddedHash = new byte[hashLength];
if (inputStream.read(embeddedHash, 0, hashLength) == -1) {
throw new Exception("stream empty");
}
// decrypt content
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
ByteArrayOutputStream decryptedStream = new ByteArrayOutputStream();
CipherInputStream cryptoStream = new CipherInputStream(inputStream, cipher);
byte[] buffer = new byte[8192];
int len;
while ((len = cryptoStream.read(buffer)) > 0) {
decryptedStream.write(buffer, 0, len);
}
return decryptedStream.toByteArray();
}
给定一个 92MB 的文件,在
while
部分,它会捕获 java.lang.OutOfMemoryError: Failed to allocate a 134086672 byte allocation with 25165824 free bytes and 36MB until OOM, target footprint 188006072, growth limit 201326592
异常。
我该如何修复它?尝试以这种方式分成块:
// decrypt content
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
ByteArrayOutputStream decryptedStream = new ByteArrayOutputStream();
byte[] buffer = new byte[8192];
int len;
while ((len = inputStream.read(buffer)) > 0) {
byte[] decryptedChunk = cipher.update(buffer, 0, len);
decryptedStream.write(decryptedChunk);
}
byte[] finalChunk = cipher.doFinal();
decryptedStream.write(finalChunk);
return decryptedStream.toByteArray();
但是没有任何改进,得到了同样的异常。你能帮我完成这个任务吗?
答案就在评论里