我有很少的AES加密視頻,在使用ExoPlayer播放前需要解密。這些視頻將被包含在應用程序的資產文件夾中,而其中很少需要放在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);
}
}
對於資產的文件夾中的錄像,我試圖直接傳遞InputStream的從getAssets().open(filePath)
回來了,但它給了相關的填充一些錯誤。所以,我用下面的代碼第一
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上進行了加密?使用上面的代碼?另外,你真的應該使用InputStream.read(),就像javadocs所說的那樣,檢查返回值以查看實際讀取的字節數。 –
@JamesKPolk不太確定,但最有可能的是。 – noob
檢查'read()'的返回值,可能是你的文件設置搞砸了。你需要仔細檢查轉換,模式和IV。 –