使用facebook隐藏文件解密文件时出现OutOfMemoryException

时间:2015-06-02 14:22:25

标签: java android facebook encryption facebook-conceal

我正在开发Android应用程序,我需要将视频保存在SD卡中,这不能转移,这就是为什么我在Facebook Conceal需要时加密和解密的原因,如果视频大小为小。

每当我尝试对10MB中不超过GenyMotion running 2.3.7的大型视频文件进行加密和解密时,它会与OutOfMemoryException崩溃,这意味着我的堆内存不足已分配给我申请无法处理但必须予以预防。

试过:

  • Apache Common Utils IO包
  • 各种IO Utils

Facebook隐瞒:解密时说

 You must read the entire stream to completion.
 The verification is done at the end of the stream.
 Thus not reading till the end of the stream will cause
 a security bug. For safety, you should not
 use any of the data until it's been fully read or throw
 away the data if an exception occurs.

代码我正在使用Facebook Conceal

调用哪种加密和解密

加密

public void startEncryption() {
    // Creates a new Crypto object with default implementations of
    // a key chain as well as native library.
    // Check for whether the crypto functionality is available
    // This might fail if android does not load libaries correctly.
    if (!crypto.isAvailable()) {
        return;
    }
    OutputStream fileStream;
    try {
        File mEncryptedFile = new File(mPlainFile.getPath().substring(0,
                mPlainFile.getPath().length() - 4)
                + "_encrypted"
                + mPlainFile.getPath().substring(
                        mPlainFile.getPath().length() - 4,
                        mPlainFile.getPath().length()));

        fileStream = new BufferedOutputStream(new FileOutputStream(
                mEncryptedFile));

        // Creates an output stream which encrypts the data as
        // it is written to it and writes it out to the file.
        OutputStream outputStream;
        outputStream = crypto.getCipherOutputStream(fileStream, entity);
        outputStream.write(FileUtils.readFileToByteArray(mPlainFile));
        // fileStream.flush();
        // fileStream.close();
        // outputStream.flush();
        // outputStream.close();
        // outputStream.flush();
        File mRenameTo = new File(mPlainFile.getPath());
        mPlainFile.delete();
        mEncryptedFile.renameTo(mRenameTo);
    } catch (FileNotFoundException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (CryptoInitializationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (KeyChainException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

解密:

public String startDecryption() {
    // Get the file to which ciphertext has been written.
    try {
        FileInputStream fileStream = new FileInputStream(mPlainFile);

        // Creates an input stream which decrypts the data as
        // it is read from it.
        InputStream inputStream;
        inputStream = crypto.getCipherInputStream(fileStream, entity);

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        // org.apache.commons.io.output.ByteArrayOutputStream out = new
        // org.apache.commons.io.output.ByteArrayOutputStream(1024);
        // Read into a byte array.
        // int read;
        // byte[] buffer = new byte[1024];
        // // You must read the entire stream to completion.
        // // The verification is done at the end of the stream.
        // // Thus not reading till the end of the stream will cause
        // // a security bug.
        // int i = 0;
        // while ((read = inputStream.read(buffer)) != -1) {
        // out.write(buffer, 0, read);
        // Log.i(TAG, "bytearrayoutputstream "+i++ + " "+read + " " +
        // buffer.length + " "+out.size());
        // }

        mDecryptedFile = new File(mPlainFile.getPath().substring(0,
                mPlainFile.getPath().length() - 4)
                + "_decrypted"
                + (mPlainFile.getPath().substring(mPlainFile.getPath()
                        .length() - 4, mPlainFile.getPath().length())));

        OutputStream outputStream = new FileOutputStream(mDecryptedFile);
        // IOUtils.copy(inputStream, outputStream);

        try {
            final byte[] buffer = new byte[1024];
            int read;

            while ((read = inputStream.read(buffer)) != -1)
                outputStream.write(buffer, 0, read);

            outputStream.flush();
        } catch (Exception e) {

        } finally {
            outputStream.close();
        }

        // out.writeTo(outputStream);
        // out.flush();
        // out.close();

        // fileStream.close();
        inputStream.close();
        // outputStream.flush();
        outputStream.close();
        return mDecryptedFile.getPath();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (CryptoInitializationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (KeyChainException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return null;
}

是否有任何解决方案可以解决并加密和解密大型视频文件?

2 个答案:

答案 0 :(得分:2)

看起来你正在将整个文件读入一个字节数组。您应该做的是创建一个输入流并将其提供给加密引擎。

所以这个:

 outputStream.write(FileUtils.readFileToByteArray(mPlainFile));

应该看起来像你的解密循环。

BufferedInputStream  bis = new BufferedInputStream(mPlainFile);
InputStream inputStream = crypto.getCipherInputStream(
                             bis,
                             entity);
while ((read = inputStream.read(buffer)) != -1) {
   outputStream.write(buffer, 0, read);
}

不确定这是不是你最终的结果。我从文档中取出了加密解码。我认为这证实了他们的意图是说必须读取流直到结束。

答案 1 :(得分:0)

正如布鲁斯所强调的那样Encryption上的瓶颈导致OutOfMemoryException Decryption时出现OutOfMemoryException。这是我在加密和解密时执行的代码,不再导致fileStream = new BufferedOutputStream(new FileOutputStream(mEncryptedFile)); OutputStream outputStream; outputStream = crypto.getCipherOutputStream(fileStream, entity); int read; byte[] buffer = new byte[1024]; BufferedInputStream bis = new BufferedInputStream(newFileInputStream(mPlainFile)); while ((read = bis.read(buffer)) != -1) { outputStream.write(buffer, 0, read); } outputStream.close(); bis.close();

加密:

InputStream inputStream;
inputStream = crypto.getCipherInputStream(fileStream, entity);
ByteArrayOutputStream out = new ByteArrayOutputStream();
OutputStream outputStream = new FileOutputStream(mDecryptedFile);
BufferedInputStream bis = new BufferedInputStream(inputStream);
int mRead;
byte[] mBuffer = new byte[1024];
while ((mRead = bis.read(mBuffer)) != -1) {
   outputStream.write(mBuffer, 0, mRead);
    }
bis.close();
out.writeTo(outputStream);
inputStream.close();
outputStream.close();
out.close();

解密:

from bs4 import BeautifulSoup

soup = BeautifulSoup(data)
div = soup.find("div", class_="myself", title=True)
print(div["title"])