为什么在Android 24+上,AESencryption/解密速度慢3倍以上?

你可以跳到TL; DR

我们有一个应用程序,它强烈依赖于AESencryption和解密。 我们希望支持尽可能多的设备,但其中的一些(尤其是蹩脚的平板电脑,我不仅仅是指中文无名字,还有一些来自三星或联想的低端平板电脑)的encryption和解密速度很慢。

我们在我们的应用程序中使用了Android 23,并且我们能够识别某种级别,在这种级别下,我们的应用程序将不能很好地为最终用户工作(他们将不得不等待内容出现太久)。 我们不得不排除使用我们的应用程序的很多平板电脑,但是,我们能够忍受这一点。

最近我们的一些依赖关系开始需要更新版本的Android。 例如,我们想切换到Facebook Core SDK,而不是完整的Facebook SDK来节省一些空间。 但是这取决于Android支持包v25,我们将无法构build它,因为proguard拒绝处理源。

所以决定把这个项目转移到一个更新的Android上。 除了对我们的encryption/解密机制的性能影响之外,它进行得非常顺利。 突然间慢了很多。 我们认为片子“足够好”的速度非常缓慢。

TL; DR

我已经开始调查从Android 23到Android 26的迁移过程中发生了什么,这会导致AESencryption/解密的性能下降。

我创build了一个应用程序,作为一种基准。 通过做一个简单的改变:

  • 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倍。 我可以在所有必须testing的设备上重现这些结果。 当然,在新的,高性能的设备上,它几乎不可见,但在旧设备上,很明显。

我已经在网上search了这方面的任何细节,但是我什么都没find。 我真的很感激有人在这个问题上提出一些看法。

我真的希望我在某个地方犯了一个错误,但是我找不到。

对于encryption/解密,我们使用SpongyCastle库。

我的Crypto Tester应用程序的源代码可在GitHub上find: https : //github.com/krstns/cryptoTester

有Android 23configuration的master_26分支和Android 26configuration的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,我知道为什么它不应该使用等。目前,这是有目的的。 这不是问题的主题,所以我们不要去那里。

Solutions Collecting From Web of "为什么在Android 24+上,AESencryption/解密速度慢3倍以上?"

你似乎直接使用SpongyCastle。 SpongyCastle是BouncyCastle(BC)的Android版本。 不过,BC是encryptionalgorithm和周边实用API的软件实现。

如果你真的想加快AES计算,你应该使用Java安全API,例如使用javax.crypto.Cipher类 。 这将允许在支持它的平台上执行硬件加速和本机代码。 通常,这将是所有平台,因为主要的encryptionfunction是在较新的平台上使用OpenSSL库实现的。

一般来说,只要所需的function在提供的encryption提供程序中不可用,build议只使用Bouncy Castle的“轻量级”API(例如您使用的软件AES实现)。 AES / CBC等algorithm绝对不是这种情况。

目前,您的库依赖于Bouncy Castle实现的字节码执行,速度要慢得多。 还要注意,Bouncy Castle不太喜欢debugging环境,因此确保在testing性能时不会延迟运行 – 如果可能的话,不需要debugging器支持。

我终于find了一个解决scheme。

当我试图在SpongyCastle GitHub上创build一个问题时,我注意到有比1.54更新的版本…我以前没有调查过这个愚蠢的问题。

只是谨慎的一句话,它在我的主要项目中并没有立即起作用。 encryption/解密机制是一个图书馆项目的一部分,然后包含在我的主要项目。 请记住也更新您的主要项目,否则它将会很慢。

所以它在以后为我工作:

  • 改变海绵城堡版本为1.56
  • 改变compileSdkVersion26
  • buildToolsVersion更改为26.0.2
  • targetSdkVersion更改为26

在图书馆项目和主要项目中。