如何改进在 92MB 文件上触发 java.lang.OutOfMemoryError 的 Decrypt 函数?

问题描述 投票:0回答:1

在 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();

但是没有任何改进,得到了同样的异常。你能帮我完成这个任务吗?

java android out-of-memory
1个回答
0
投票

答案就在评论里

© www.soinside.com 2019 - 2024. All rights reserved.