3

I need to make a simple sort of encryption so that the normal end user can't access some files easily.

The files that are read by an FileInputStream are html files, pngs, jpegs and different simple text files (javascript, xml, ...)

What I currently do is this:

public static byte[] toEncryptedByteArray(InputStream input) throws IOException {
    ByteArrayOutputStream output = new ByteArrayOutputStream();
    copy(input, output, true);
    return output.toByteArray();
}

public synchronized static final int copy(final InputStream input, final OutputStream output, final boolean modify) throws IOException {
    if (input == null || output == null) {
        throw new IOException("One stream is null!");
    }
    byte[] mBuffer = new byte[DEFAULT_BUFFER_SIZE];
    int count = 0;
    int n;
    while ((n = input.read(mBuffer)) != -1) {
        if (modify) {
            for ( int i = 0 ; i < n ; i++ ) {
                mBuffer[i] = (byte) ~mBuffer[i]; // byte manipulation
            }
        }
        output.write(mBuffer, 0, n);
        output.flush();
        count += n;
    }
    mBuffer = null;
    return count;
}

The memory footprint is huge as I have the complete byte array in my memory (we talk about bitmaps with >2mb in memory).

I thought I could simple extend the FileInputStream class and do the byte manipulation while reading the content of the file. That would reduce the memory usage as I could use Bitmap.decodeStream(inputstream) instead of creating a byte array to get the bitmap from... but here I am stuck totally. The read() and the readBytes(...) methods are native, so I can't override them.

Please spread the light in my darkness...

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
WarrenFaith
  • 57,492
  • 25
  • 134
  • 150

2 Answers2

2

Streams are designed to wrap. That's why you frequently see lines like:

InputStream is=new BufferedInputStream(new FileInputStream(file));

So, create a DecryptingInputStream that does your decryption, wrapping around another InputStream.

All that being said, this won't be tough to crack, as your decryption keys and algorithm will be easily determinable by anyone who decompiles your app.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Well, this kind of decryption is just to scramble the files on the sdcard. Just to stop the normal user from copying the files from the phone. Wrapping will not reduce the memory usage, right? The way I have to modify the bytes is the same. Or am I wrong? – WarrenFaith Sep 27 '11 at 18:33
  • @WarrenFaith: "Wrapping will not reduce the memory usage, right?" -- it will as much as overriding the methods would. – CommonsWare Sep 27 '11 at 18:44
0

FileInputStream is not your problem. The read() function will not read in more than DEFAULT_BUFFER_SIZE on each call. It is your use of ByteArrayOutputStream which is using up a lot of memory as your are writing to it.

If you want to reduce the amount of memory required then I suggest you write directly to a FileOutputStream instead of a ByteArrayOutputStream. So encrypt and write to disk as you read DEFAULT_BUFFER_SIZE from the InputStream.

vee
  • 720
  • 7
  • 8
  • I don't save it on the disk. It is already encrypted saved on the disk. I need an on-the-fly decryption while reading from the disk. As my current implementation decrypt outside the InputStream, I need a byte array to perform the decryption. That is the reason I need the array. I will try to wrap it like CommonsWare suggested. – WarrenFaith Sep 27 '11 at 20:39