You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack加密文件解密失败:读取加密文件返回-1字节无结果

解密EncryptedFile返回-1字节的问题修复

问题根源

你的代码存在核心错误:加密完成后直接复用同一个EncryptedFile实例调用openFileInput()读取文件。该实例是为写入加密文件创建的,关闭输出流后内部状态已无法正确初始化输入流,导致读取返回-1(表示流无内容/已结束)。此外,用ByteArrayOutputStream将整个文件读入内存的方式,处理大文件时会触发内存溢出,也需优化。

修复方案

  1. 加密完成后重新创建EncryptedFile实例用于读取/解密
  2. 使用流缓冲区直接拷贝替代全内存读取,提升性能并避免OOM
  3. 用try-with-resources自动管理流资源,杜绝资源泄漏

修正后的代码

try {
    File fileToEncrypt = new File(fileModel.getFilePath());
    if (fileToEncrypt.exists()) {
        File encryptedFile = new File(fileHelper.getAppPhotosDirectory(), fileToEncrypt.getName());
        if (encryptedFile.exists()) encryptedFile.delete();

        // 初始化MasterKey(可提取为复用方法)
        KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(
                MasterKey.DEFAULT_MASTER_KEY_ALIAS,
                KeyProperties.PURPOSE_DECRYPT | KeyProperties.PURPOSE_ENCRYPT)
                .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
                .setKeySize(256)
                .build();

        MasterKey masterKey = new MasterKey.Builder(requireContext().getApplicationContext(), MasterKey.DEFAULT_MASTER_KEY_ALIAS)
                .setKeyGenParameterSpec(keyGenParameterSpec)
                .build();

        // --- 加密文件:用流缓冲区拷贝,避免全内存加载 ---
        try (FileInputStream fis = new FileInputStream(fileToEncrypt);
             EncryptedFile encryptedFileWriter = new EncryptedFile.Builder(
                     requireContext().getApplicationContext(),
                     encryptedFile,
                     masterKey,
                     EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB)
                     .build();
             OutputStream os = encryptedFileWriter.openFileOutput()) {

            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = fis.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            // try-with-resources会自动关闭流,无需手动flush/close
        }

        if (encryptedFile.exists()) {
            FileModel encryptedFileModel = new FileModel(encryptedFile.getName(), encryptedFile.getPath());
            Log.d("analyze", "File encrypted in: " + encryptedFileModel.getFilePath());
            Log.d("analyze", "Now decrypting file again: " + encryptedFileModel.getFilePath());

            // --- 关键:重新创建EncryptedFile实例用于读取 ---
            try (EncryptedFile encryptedFileReader = new EncryptedFile.Builder(
                     requireContext().getApplicationContext(),
                     encryptedFile,
                     masterKey,
                     EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB)
                     .build();
                 InputStream is = encryptedFileReader.openFileInput()) {

                int firstByte = is.read();
                Log.d("analyze", "First byte from file: " + firstByte);
                // 此处可继续读取完整文件内容进行解密
            }
        } else {
            Log.d("analyze", "File not encrypted");
        }
    }
} catch (GeneralSecurityException | IOException e) {
    e.printStackTrace();
}

关键改动说明

  • 提取MasterKey初始化逻辑,避免重复创建冗余实例
  • 采用try-with-resources自动管理流资源,确保资源正确释放
  • 加密时用8KB缓冲区的流拷贝替代全内存读取,适配大文件场景
  • 读取加密文件时重新创建EncryptedFile实例,确保输入流正确初始化

内容的提问来源于stack exchange,提问作者HabibUllah786

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 01:25:19