Search code examples
javaandroidencryptionvideo-streamingdrm

Not able to seek large cipher stream


its been two weeks and still we are running errands.

The scenario,

we managed to stream encrypted video using a local web server inspired by this. Link

the problem is when seeking (Progress Bar of the video hangs, same works for normal file). CipherInputStream.Seek(pos) does not seek beyond the buffer.

CipherInputStream cis = null;
...
long skipped = cis.skip(cbSkip);

skipped is always zero for long jumps. Link

so we are resorting to BlockSize 1 (weak encryption) so that seeking will become implicit.

i believe ARC4 is no more included in android Ref Link. (please tell me that i am misinformed), or is there any other encryption (supported by android) which will have block size 1.

as the constructor of CipherInputStream has,

if (!(isStream = cipher.getBlockSize() == 1))

which will not override the superclass behavior.

so left with few option like including ARC4 (or some other custom byte in byte out encryption) for seeking.

is there any chance our lives can be made simple. we just need some sort of encryption for media which mitigates a casual user. (speed breaker)

Any one answer will solve this problem:

  • Is there any android supported algorithm which has block size as 1
  • Or do you have links which points to similar local decrypted streaming solutions which is seekable.
  • Or do we have DIY option only.

Solution

  • Try counter mode encryption (CTR). Counter mode encryption is also used in e.g. disk encryption: it is not dependent on any previous blocks like CBC is. You may have to jump to a specific block and then jump to the specific byte within the block though. You should use GCM for "integrity control" if that is what you're after. Have a look at what's available in bouncy castle regarding these algo's (a bit of a warning: you may get into trouble using AES keys with Android because the library has been (badly) integrated in Android.