【发布时间】:2018-03-27 15:09:59
【问题描述】:
您可以跳到 TL;DR
我们有一个应用程序,它强烈依赖于 AES 加密和解密。我们希望支持尽可能多的设备,但其中一些设备(尤其是蹩脚的平板电脑,我指的不仅是中国的无名,还有一些三星或联想的低端平板电脑)的加密和解密速度很慢。
我们在我们的应用中使用了 Android 23,并且我们能够识别出某种级别,低于该级别我们的应用对于最终用户将无法正常工作(他们必须等待太长时间才能显示内容)。我们不得不排除很多平板电脑与我们的应用程序一起使用,但是,我们能够忍受这些。
最近我们的一些依赖项开始需要更新版本的 Android。例如,我们想切换到 Facebook Core SDK,而不是完整的 Facebook SDK 以节省一些空间。但它依赖于 Android 支持包 v25,我们将无法构建它,因为 proguard 拒绝处理源代码。
因此决定将项目转移到更新的 Android 上。除了它对我们的加密/解密机制的性能影响之外,它非常顺利。突然间慢了很多。我们评价为“运行良好”的平板电脑非常慢。
TL;DR
我已经开始调查在我们从 Android 23 迁移到 Android 26 期间发生了什么,这会导致 AES 加密/解密的性能大幅下降。
我创建了一个应用程序,它可以作为一种基准。通过做一个简单的改变:
compileSdkVersion 23->26targetSdkVersion 23->26compile 'com.android.support:appcompat-v7:VERSION' 23.4.0 -> 26.+
性能下降很大。
以下是其中一款平板电脑的示例结果:
Android 23: 136959 B/s
Android 26: 34419 B/s
这几乎慢了 4 倍。我可以在我必须测试的所有设备上重现这些结果。当然,在新的高性能设备上几乎看不到它,但在旧设备上却很明显。
我已经在网上搜索了有关这方面的任何详细信息,但我一无所获。我真的很感激有人能阐明这个问题。
我真的希望我在某个地方犯了错误,但我找不到它。
对于加密/解密,我们使用 SpongyCastle 库。
我的 Crypto Tester 应用程序的源代码可在 GitHub 上找到:https://github.com/krstns/cryptoTester
master 分支采用 Android 23 配置,master_26 分支采用 Android 26 配置。
为了完整起见,我把解密的方法贴在这里:
/**
* Decrypt the given data with the given key
*
* @param data The data to decrypt
* @return The decrypted bytes
*/
public static byte[] decrypt(byte[] data, byte[] key, byte[] iv) {
if (key == null || iv == null) {
throw new AssertionError("DECRYPT: Key or iv were not specified.");
}
// make sure key is AES256
byte[] bookKeyData = new byte[32];
byte[] outBuf;
System.arraycopy(key, 0, bookKeyData, 0, key.length);
try {
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESFastEngine()));
cipher.init(false, new ParametersWithIV(new KeyParameter(bookKeyData), iv));
int outputSize = cipher.getOutputSize(data.length);
outBuf = new byte[cipher.getOutputSize(outputSize)];
int processed = cipher.processBytes(data, 0, data.length, outBuf, 0);
if (processed < outputSize) {
processed += cipher.doFinal(outBuf, processed);
}
return Arrays.copyOfRange(outBuf, 0, processed);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
哦,是的。我知道这是 CBC,我知道为什么不应该使用它等等。目前,它是故意完成的。这不是问题的主题,所以我们不要去那里。
【问题讨论】:
-
加解密算法是否应该使用硬件加速?
-
我不知道,我认为这是由操作系统/库在幕后完成的。
-
136959 B/s (136 kB/s) 本身就有点糟糕。也许您需要调查两台机器的一般问题。从餐巾纸的背面看,这对于 200 MHz 处理器来说可能没问题。您应该开始比较每字节周期数 (cpb)。这将回避处理器速度并检查算法和实现效率。您应该在 32 位 ARM 上的软件目标为 30 到 60 cpb,在 64 位 ARM 上的硬件目标为 2 到 5 cpb。 900 MHz Beaglebone (A-32) 达到 45 cpb 或 20 MB/s。 2.0 GHz Opeteron (Aarch64) 达到 1.0 cpb 和 1.8 GB/s。
-
@jww 很可能只是我的计算是废话;)但是这些值显示了性能下降的规模,即使它们可能不是 B/s。我将对此进行进一步调查。如果解密 10MB 需要几秒钟,它不可能是 136kB/s。对此感到抱歉。
标签: java android performance encryption cryptography