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

标签 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 也不会改变任何东西。

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

最佳答案

我在运行 Android 4.4.4 的 Google 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”

关于android - 将字节从 FileInputStream 复制到 CipherOutputStream(反之亦然)非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25607270/

相关文章:

android - 防止按返回按钮取消操作模式

android - 使用 FragmentActivity 的 getSupportActionBar

iphone - iOS 如何加密和解密二进制文件?

c# - 从证书中提取公钥

android - 使用 FileProvider Android 从可移动 SD 卡打开文件时出错

android - 存储访问框架 : keep file permissions after revoke tree permissions

c - 如何使用 mbedtls 以 aes 方式加密字符串?

java - 使用 salt 将 Rijndael 解密从 PHP 移植到 Java

java - 使用 java ssl 套接字时是否也需要加密流?

java - 使用此椭圆曲线点乘法计算的点不在曲线上,此类带来算术异常