android - 无法在 Android 上使用 AES 密码读取加密视频

标签 android video encryption aes

我必须在 Android 设备上阅读加密视频。

我使用 http://elonen.iki.fi/code/nanohttpd/ 创建了一个本地主机服务器它以一种非常简单的方式允许这样做。

我用它来读取未加密的视频,但我仍然无法读取加密的视频。 (视频加密我不嫌麻烦,就为了看)

我尝试了以下方法:

1- 使用简单的“AES”加密视频,当我尝试用我的服务器读取它时,我看到流式传输开始(我看到我的服务器以不同的范围响应 3 次)。 播放 3 次后播放器说无法阅读视频。

2- 使用“AES/CTR/NoPadding”加密视频:在这种情况下,我看到我的服务器提供了第一个范围并且一次又一次地运行但没有视频显示。

我尝试使用 CTR16 获取 16 位的 block ,并使用 32ko 的缓冲区读取它们。那是行不通的。

(PS:我用我的方法解密图片没问题)

这里是我的加密方法:

public static InputStream getUncryptInputStream(InputStream is, String pass, final long dataLen) throws Exception{
        SecretKeySpec key = new SecretKeySpec(getRawKey(pass.getBytes()), "AES");
        Cipher mCipher = Cipher.getInstance("AES/CTR/NoPadding");
        mCipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
        if(dataLen==-1){
            return new CipherInputStream(is, mCipher);
        }else{
            return new CipherInputStreamWithDataLen(is, mCipher, dataLen);
        }
}

public static OutputStream getCryptOutputStream(OutputStream os, String pass) throws Exception{
    SecretKeySpec key = new SecretKeySpec(getRawKey(pass.getBytes()), "AES");

    Cipher mCipher = Cipher.getInstance("AES/CTR/NoPadding");
    mCipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);

    return new CipherOutputStream(os, mCipher);

}

private static byte[] getRawKey(byte[] seed) throws Exception {
    KeyGenerator kgen = KeyGenerator.getInstance("AES");
    SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
    sr.setSeed(seed);
    kgen.init(128, sr); // 192 and 256 bits may not be available
    SecretKey skey = kgen.generateKey();
    byte[] raw = skey.getEncoded();
    return raw;
}

和我创建的 CipherInputStreamWithData 因为可用的方法总是返回 0 和正常的 CipherInputStreamWithData:

import java.io.IOException;
import java.io.InputStream;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;

public class CipherInputStreamWithDataLen extends CipherInputStream{

    int dataLen;

    public CipherInputStreamWithDataLen(InputStream is, Cipher mCipher, long dataLen) {
        super(is, mCipher);
        this.dataLen = (int)dataLen;
        // TODO Auto-generated constructor stub
    }

    public int available() throws IOException{
        return dataLen;
    }

}

最佳答案

问题是因为 CipherInputStream skip 方法。

  1. 由于密码加密,您必须小心跳过直到最后一个 cipherBlock,然后解密最后一个 +1 cupherblock 以获得您需要写入 BufferedOutputStream 的几个额外字节
  2. 如果 CipherInputStream 的“available”方法返回的值小于要跳过的字节数,则 skip 方法将跳过的最大字节数将等于“available”方法返回的值。

一般评论:在视频开始之前,使用大型 BufferedInputStream 需要大约 10 秒的时间。 有人建议使用 NDK 以原生方式对 AES 进行编码。 根据我的需要,我只编写了一个简单的 XOR。

关于android - 无法在 Android 上使用 AES 密码读取加密视频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11583719/

相关文章:

java - 单击通知后从后台打开应用程序后运行函数

android - 如何根据 android 中的 CPU 能力加载不同的 jni 库?

ios - AVPlayer 帧动画

java - 使用 XOR JAVA 解密仅在第一行工作

机器人 : get current position of videos in webview

java - 为什么 'toast' 消息在 Android 中不起作用?无法修复bug,请帮忙!

视频在 Quicktime 中有多种分辨率,但 ffmpeg 只能看到一种

ios - AVAudioSession 在混合和非混合模式之间切换

java - Tomcat 8 Manager war deploy 上传通过 SSL 失败

c - 使用 cjsoe 进行 JSON Web 加密