您可以跳至TL; DR
我们有一个应用程序,它强烈依赖于AES加密和解密。我们希望尽可能多地支持设备,但其中一些(特别是糟糕的平板电脑,我不仅仅是指中文无名,还有一些来自三星或联想的低端平板电脑)加密和解密速度很慢。
我们在我们的应用程序中使用了Android 23,我们能够确定某种级别,在这种级别之下,我们的应用程序根本不适合最终用户(他们必须等待太长时间才能显示内容)。很多平板电脑我们不得不排除在我们的应用程序中使用,但是,我们能够忍受它。
最近我们的一些依赖项开始需要更新版本的Android。例如,我们想切换到Facebook Core SDK,而不是完整的Facebook SDK以节省一些空间。但这取决于Android支持包v25,我们将无法构建它,因为proguard拒绝处理源。
因此决定将项目转移到更新的Android。除了它对我们的加密/解密机制的性能影响之外,它还是非常顺利。突然间,它慢得多。平板电脑我们认为“工作得足够好”非常慢。
TL; DR
我已经开始调查从Android 23迁移到Android 26期间发生的事情,这会导致AES加密/解密性能大幅下降。
我创建了一个应用程序,它可以作为一种基准。通过简单的改变:
compileSdkVersion 23->26
targetSdkVersion 23->26
compile '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
有{23}配置的master
分支和Android 26配置的master_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,我知道为什么不应该使用等等。目前,它是故意的。这不是问题的主题,所以我们不要去那里。
答案 0 :(得分:3)
您似乎直接使用SpongyCastle。 SpongyCastle是BouncyCastle(BC)的Android版本。然而,BC是加密算法和周围实用程序API的仅软件实现。
如果您真的想加快AES计算,那么您应该使用Java Security API,例如:使用javax.crypto.Cipher
class。这将允许在支持它的平台上进行硬件加速和本机代码执行。通常,这将是所有平台,因为主要的加密功能是在较新的平台上使用OpenSSL库实现的。
一般情况下,建议只使用Bouncy Castle&#34;轻量级&#34;只要在提供的Cryptography 提供程序中没有所需的功能,API就会使用API(例如您正在使用的软件AES实现)。对于诸如AES / CBC之类的算法,这绝对是不。
目前,您的库依赖于Bouncy Castle实现的字节代码执行,这要慢得多。另请注意,Bouncy Castle不太喜欢调试环境,所以在测试性能时确保它没有延迟运行 - 如果可能的话没有调试器支持。
答案 1 :(得分:2)
我终于找到了解决方案。
当我尝试在SpongyCastle GitHub上创建一个问题时,我注意到有比1.54
更新的版本......对于我之前没有对此进行调查,我很傻。
请注意,它在我的主项目中并没有立即发挥作用。加密/解密机制是库项目的一部分,然后包含在我的主项目中。请记住也要更新你的主项目,否则它仍然会很慢。
所以它对我有用:
1.56
compileSdkVersion
更改为26
buildToolsVersion
更改为26.0.2
targetSdkVersion
更改为26
在图书馆项目和主要项目中。