【问题标题】:Last block incomplete in decryption while decrypting a file解密文件时,最后一个块在解密中不完整
【发布时间】:2017-05-12 14:33:07
【问题描述】:

在使用 ExoPlayer 播放之前,我需要解密一些 AES 加密视频。这些视频将包含在应用程序的资产文件夹中,而其中很少一部分需要放在 SD 卡上。

我一直在使用提供的实用程序类来解密视频,但它似乎无法正常工作。

static String key = "xxx"; // key should be exactly 16bit long
private static final String ALGORITHM = "AES";
private static final String TRANSFORMATION = "AES";

public static void encrypt(File inputFile, File outputFile) throws CryptoException {
    doCrypto(Cipher.ENCRYPT_MODE, inputFile, outputFile);
}
public static void decrypt(File inputFile, File outputFile) throws CryptoException {
    doCrypto(Cipher.DECRYPT_MODE, inputFile, outputFile);
}

private static void doCrypto(int cipherMode, File inputFile, File outputFile) throws CryptoException {
    try {
        Key secretKey = new SecretKeySpec(key.getBytes(), ALGORITHM);
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(cipherMode, secretKey);

        FileInputStream inputStream = new FileInputStream(inputFile);
        byte[] inputBytes = new byte[(int) inputFile.length()];
        inputStream.read(inputBytes);

        byte[] outputBytes = cipher.doFinal(inputBytes);

        FileOutputStream outputStream = new FileOutputStream(outputFile);
        outputStream.write(outputBytes);

        inputStream.close();
        outputStream.close();
    } catch (IOException | NoSuchAlgorithmException | InvalidKeyException | NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException e) {
        e.printStackTrace();
        throw new CryptoException("Error encrypting/decrypting file", e);
    }
}

对于 assets 文件夹中的视频,我尝试直接传递从 getAssets().open(filePath) 返回的 InputStream,但是它给出了一些与填充有关的错误。所以我首先使用以下代码将视频文件复制到内部存储

public static void copyFromAssets(Context context, String filePath, File outputFile) {
    InputStream in = null;
    OutputStream out = null;
    try {
        in = context.getAssets().open(filePath);
        out = new FileOutputStream(outputFile);
        copyFile(in, out);
    } catch (IOException e) {
        e.printStackTrace();
        LumberJack.e("tag", "Failed to copy asset file: " + filePath);
    } finally {
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
            }
        }
        if (out != null) {
            try {
                out.close();
            } catch (IOException e) {
                // NOOP
            }
        }
    }
}

private static void copyFile(InputStream in, OutputStream out) throws IOException {
    byte[] buffer = new byte[1024];
    int read;
    while ((read = in.read(buffer)) != -1) {
        out.write(buffer, 0, read);
    }
}

视频在那里,但由于它是加密视频,我无法播放。当我尝试解密提取的视频文件时,出现以下异常 -

javax.crypto.IllegalBlockSizeException: last block incomplete in decryption
     at com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(BaseBlockCipher.java:853)
     at javax.crypto.Cipher.doFinal(Cipher.java:1502)
     at com.example.utilities.CryptoUtils.doCrypto(CryptoUtils.java:42)
     at com.example.utilities.CryptoUtils.decrypt(CryptoUtils.java:29)
     at com.example.activities.HomeActivity.onVideoPlayButtonClick(HomeActivity.java:107)
     at java.lang.reflect.Method.invoke(Native Method)
     at org.greenrobot.eventbus.EventBus.invokeSubscriber(EventBus.java:485)
     at org.greenrobot.eventbus.EventBus.postToSubscription(EventBus.java:420)
     at org.greenrobot.eventbus.EventBus.postSingleEventForEventType(EventBus.java:397)
     at org.greenrobot.eventbus.EventBus.postSingleEvent(EventBus.java:370)
     at org.greenrobot.eventbus.EventBus.post(EventBus.java:251)
     at com.example.viewmodels.BaseDataLevelItemView$1.onClick(BaseDataLevelItemView.java:65)
     at android.view.View.performClick(View.java:5210)
     at android.view.View$PerformClick.run(View.java:21169)
     at android.os.Handler.handleCallback(Handler.java:739)
     at android.os.Handler.dispatchMessage(Handler.java:95)
     at android.os.Looper.loop(Looper.java:148)
     at android.app.ActivityThread.main(ActivityThread.java:5451)
     at java.lang.reflect.Method.invoke(Native Method)
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

我不确定我在这里做错了什么。相同的解密代码已在具有相同视频的应用程序的早期版本中使用,但现在出现问题。我已经检查了 Stackoverflow 上与同一异常相关的其他一些答案,但其中大部分都与密文中的编码问题有关。我这里没有字符串,而是一个文件。

如果您已经发现了问题,我该如何找出问题所在,以及如何纠正它?

【问题讨论】:

  • 文件是否也在 Android 上加密?使用上面的代码?此外,您确实应该按照 javadocs 所说的方式使用 Inputstream.read(),检查返回值以查看实际读取了多少字节。
  • @JamesKPolk 不太确定,但很可能是的。
  • 检查read()的返回值,可能你的文件设置搞砸了。您需要仔细检查转换、模式和 IV。
  • 错误的键会导致填充错误。您是否收到您自己加密的文件的错误?另外..您应该完全限定您的转换(如“算法/模式/填充”),因为不同的安全提供者可能不会使用相同的默认值。

标签: java android video encryption cryptography


【解决方案1】:

感谢Ebbe M. Pedersen 的建议,我实际上尝试加密文件并尝试使用相同的代码进行解密。
因此,确认有其他算法或其他方法用于加密文件。幸运的是,我在旧的提交中找到了它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-06-11
    • 2012-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    相关资源
    最近更新 更多