1

Android デバイスで暗号化されたビデオを読まなければなりません。

http://elonen.iki.fi/code/nanohttpd/を使用して localhost サーバーを作成しました。これにより、非常に簡単な方法でこれが可能になります。

暗号化されていないビデオを読み取ることはできますが、暗号化されたビデオの読み取りに行き詰まっています。(ビデオを暗号化するのに問題はありません。読むだけです)

私は次のことを試しました:

1-単純な「AES」を使用してビデオを暗号化し、サーバーで読み取ろうとすると、ストリーミングが開始されます(サーバーがさまざまな範囲で3回応答するのが見えます)。3 回後、プレーヤーはビデオを読むことができないと言います。

2-「AES/CTR/NoPadding」を使用してビデオを暗号化するには: その場合、最初の範囲を配信し、何度も何度も実行されているサーバーが表示されますが、ビデオは表示されません。

CTR16 を使用して 16 ビットのブロックを取得し、32ko のバッファーでそれらを読み取ろうとしました。それはうまくいきません。

(PS:私の方法で画像を復号化するのに問題はありません)

ここで私のcryptメソッド:

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;
    }

}
4

1 に答える 1

1

問題は、CipherInputStream スキップ メソッドが原因でした。

  1. サイファー暗号化のため、最後の cipherBlock までスキップし、最後の +1 個の cupherblock を復号化して、BufferedOutputStream に書き込む必要のある追加のバイトを取得するように注意する必要があります。
  2. CipherInputStream からの「available」メソッドによって返される値が < からスキップするバイト数の場合、skip メソッドがスキップする最大バイト数は「available」メソッドによって返される値と等しくなります。

一般的なコメント : 大きな BufferedInputStream を使用すると、ビデオが開始するまでに約 10 秒かかります。一部の人々は、NDK を使用してネイティブで AES をコーディングすることを提案しています。私の必要に応じて、単純な XOR をコーディングするだけです。

于 2012-07-24T12:33:18.853 に答える