将字节从FileInputStream复制到CipherOutputStream(反之亦然)非常慢

时间:2014-09-01 13:49:00

标签: android encryption cryptography inputstream filestream

我一直在关注教程“How do I encrypt and decrypt files using DES?”,为现有的Android 4+应用添加简单的文件加密。

一切正常,但加密和解密非常非常慢。

以下两种方法几乎都是完整的教程:

public static void encryptOrDecrypt(String key, int mode, InputStream is, OutputStream os) throws Throwable {
    DESKeySpec dks = new DESKeySpec(key.getBytes());
    SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
    SecretKey desKey = skf.generateSecret(dks);
    Cipher cipher = Cipher.getInstance("DES"); // DES/ECB/PKCS5Padding for SunJCE

    if (mode == Cipher.ENCRYPT_MODE) {
        cipher.init(Cipher.ENCRYPT_MODE, desKey);
        CipherInputStream cis = new CipherInputStream(is, cipher);
        doCopy(cis, os);
    } else if (mode == Cipher.DECRYPT_MODE) {
        cipher.init(Cipher.DECRYPT_MODE, desKey);
        CipherOutputStream cos = new CipherOutputStream(os, cipher);
        doCopy(is, cos);
    }
}

public static void doCopy(InputStream is, OutputStream os) throws IOException {
    byte[] bytes = new byte[64];
    int numBytes;

    // Why is this taking so long?
    while ((numBytes = is.read(bytes)) != -1) {
        os.write(bytes, 0, numBytes);
    }

    os.flush();
    os.close();
    is.close();
}

非常简单和基本,但是对1 MB文件进行解密/加密需要大约20-30秒。详细说明,它是在两个流之间复制字节的while循环,这是这么慢。

将byte []的大小更改为更大的值(如65536)以一次读取更多字节不会改变任何内容。我认为一次读取更多字节会加快进程但这是不是这样的。

在没有加密的情况下在“普通”流之间复制数据并不需要很长时间。这种加密真的是加密吗?我一直在其他平台上使用类似的加密,这种延迟从来都不是问题。

本教程使用DES,但将算法更改为不同的算法,例如AES也没有改变任何东西。

我有什么想法可以加快速度吗?

2 个答案:

答案 0 :(得分:3)

我在运行Android 4.4.4的谷歌LG Nexus 5上进行了一些实验,基本上使用了代码并加密了一个1000000(一百万)字节的文件,读取/写入/ sdcard文件系统。

no crypt 1421 ms
AES ECB mode 2577 ms
DES ECB 3214

接下来,我稍微修改了您的代码,以使用BufferedInputStreamBufferedOutputStream

no crypt 88 ms
AES ECB mode 855 ms
DES ECB mode 1419 MS

这表明时间对缓冲很敏感,并且AES比DES快。

提供商名称是' AndroidOpenSSL'

答案 1 :(得分:1)

某些进程阻止输入文件可能会出现问题。要测试问题是否是这样:计算应该读取的文件的最后部分以及将要读取的完整缓冲区的计数。用for循环替换while,如果文件大小/缓冲区大小有剩余,则添加额外的读写。