Yop
Yop

Reputation: 115

Impossible to read crypt Video with AES Cipher on Android

I have to read an encrypted video on Android device.

I created a localhost server using http://elonen.iki.fi/code/nanohttpd/ which permits this in a very simple way.

I achieve with it to read unencrypted videos but I am stuck at reading the encrypted videos. (I don't have any trouble to encrypt the video, just to read it)

I tried the following:

1- To encrypt video using a simple "AES", and when I try to read it with my server, I see the streaming starts (I see my server answering 3 times with various range). After 3 times the player says that is impossible to read the video.

2- To encrypt the video using "AES/CTR/NoPadding": in that case, I see my server that delivers the first range and that iss running again and again and again but no video displays.

I try with CTR16 to get block of 16 bits, and to read them with a bufer of 32ko. That does not work.

(PS : I have no problem to uncrypt picture with my method)

Here my crypt method :

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

and the CipherInputStreamWithData I created because the method available always returns 0 with the normal 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;
    }

}

Upvotes: 1

Views: 1148

Answers (1)

Yop
Yop

Reputation: 115

The problem was because of the CipherInputStream skip method.

  1. because of the cypher encryptation, you have to take care to skip untill the last cipherBlock and then decrypt the last+1 cupherblock to get the few additional bytes you need to write into your BufferedOutputStream
  2. if the value return by the "available" method from CipherInputStream is < to the number of bytes to skip, the maximum of bytes that the skip method will skip will be equal to the value return by the "available" method.

General Comment : It takes arround 10s with a large BufferedInputStream before a video starts. Some people suggests to use the NDK to code the AES in native. For my need I just code a simple XOR.

Upvotes: 1

Related Questions