Problems with facebooks conceal library

2019-09-01 08:58发布

问题:

I'm having issues with reading decrypted data from conceal. It looks like I can't correctly finish streaming. I pretend there is some issue with conceal, because of when I switch my proxyStream (just the encryption part) to not run it through conceal, everything works as expected. I'm also assuming that writing is ok, there is no exception whatsoever and I can find the encrypted file on disk.

I'm proxying my data through contentprovider to allow other apps read decrypted data when the user wants it. (sharing,...)

In my content provider I'm using the openFile method to allow contentResolvers read the data

@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {

    try {
        ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
        String name = uri.getLastPathSegment();
        File file = new File(name);
        InputStream fileContents = mStorageProxy.getDecryptInputStream(file);
        ParcelFileDescriptor.AutoCloseOutputStream stream = new ParcelFileDescriptor.AutoCloseOutputStream(pipe[1]);
        PipeThread pipeThread = new PipeThread(fileContents, stream);
        pipeThread.start();
        return pipe[0];
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

I guess in the Facebook app Facebook android team could be rather using a standard query() method with a byte array sent in MediaStore.MediaColumns() which is not suitable for me because of I'm not only encrypting media files and I also like the approach of streams better.

This is how I'm reading from the Inpustream. It's basically a pipe between two parcelFileDescriptors. The inputstream comes from conceal and it is a FileInputstream wrapped into a BufferedInputStream originaly.

static class PipeThread extends Thread {
    InputStream input;
    OutputStream out;

    PipeThread(InputStream inputStream, OutputStream out) {
        this.input=inputStream;
        this.out=out;
    }

    @Override
    public void run() {
            byte[] buf=new byte[1024];
            int len;

            try {
                while ((len=input.read(buf)) > 0) {
                    out.write(buf, 0, len);
                }

                input.close();
                out.flush();
                out.close();
            }
        catch (IOException e) {
            Log.e(getClass().getSimpleName(),
                "Exception transferring file", e);
        }
    }
}

I've tried other methods how to read the stream, so it really shouldn't be the issue.

Finally here's the exception I'm constantly ending up with. Do you know what could be the issue? It points to native calls, which I got lost in..

Exception transferring file
com.facebook.crypto.cipher.NativeGCMCipherException: decryptFinal
        at com.facebook.crypto.cipher.NativeGCMCipher.decryptFinal(NativeGCMCipher.java:108)
        at com.facebook.crypto.streams.NativeGCMCipherInputStream.ensureTagValid(NativeGCMCipherInputStream.java:126)
        at com.facebook.crypto.streams.NativeGCMCipherInputStream.read(NativeGCMCipherInputStream.java:91)
        at com.facebook.crypto.streams.NativeGCMCipherInputStream.read(NativeGCMCipherInputStream.java:76)

EDIT: It looks like the stream is working ok, but what fails is the last iteration of reading from it. As I'm using buffer it seems like the fact that the buffer is bigger then the amount of remaiming data is causing the issue. I've been looking into sources of conceal and it seems to be ok from this regard there. Couldn't it be failing somewhere in the native layer? Note: I've managed to get the decrypted file except its final chunk of bytes..So I have for example an incomplete image file (with last few thousands of pixels not being displayed)

回答1:

This was resolved in https://github.com/facebook/conceal/issues/24. For posterity's sake, the problem here is that the author forgot to call close() on the output stream.



回答2:

From my little experience with conceal, I have noticed that, only the same application that encrypts a file could decrypt it successfully irrespective whether it has the same package or not. Be sure to put this in mind