Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is AES encryption / decryption more than 3x slower on Android 24+?

You can skip to TL;DR

We have an app, which strongly relies on AES encryption and decryption. We want to support as many devices as possible, but some of them (especially crappy tablets and I don't only mean Chinese no-names, but also some low-end tablets from Samsung or Lenovo) are simply slow to encrypt and decrypt.

We have used Android 23 in our app and we were able to identify some kind of level below which our app will simply not work well for the end user (they would have to wait too long for the content to appear). It was a lot of tablets that we had to rule out for use with our app, but well, we were able to live with that.

Recently some of our dependencies started to require a newer version of Android. For example, we wanted to switch to Facebook Core SDK, instead of the full Facebook SDK to save some space. But it depends on the Android support package v25 and we won't be able to build it because proguard refuses to process the sources.

So a decision was made to move the project to a newer Android. It went quite smooth, apart from the performance impact it had on our encryption/decryption mechanism. Suddenly it was MUCH slower. Tablets we would rate as "working well enough" were extremely slow.

TL;DR

I've started to investigate what happened during our migration from Android 23 to Android 26, which would cause a HUGE performance drop in AES encryption/decryption.

I've created an app, which works as kind of a benchmark. By making a simple change:

  • compileSdkVersion 23->26
  • targetSdkVersion 23->26
  • compile 'com.android.support:appcompat-v7:VERSION' 23.4.0 -> 26.+

the performance drop is huge.

Here's an example result from one of the tablets:

Android 23: 136959 B/s
Android 26: 34419 B/s

That's almost 4x slower. I can reproduce these results on all of the devices I have to test. Sure, on new, high-performance devices it's barely visible, but on old devices, it's clear.

I've searched the web for any details on this, but I have found nothing. I would really be grateful for someone to shed some light on this issue.

I really hope I have made a mistake somewhere, but I wasn't able to find it.

For encryption/decryption, we use the SpongyCastle library.

The sources of my Crypto Tester app are available on GitHub: https://github.com/krstns/cryptoTester

There's the master branch with Android 23 configuration and master_26 branch with Android 26 configuration.

For the sake of completeness, I will paste here the method which is used for decryption:

/**
 * 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;
}

Oh and.. yes. I am aware this is CBC, I am aware of why it should not be used etc. Currently, it is done on purpose. This is not the topic of the question, so let's not go there.

like image 990
Krystian Avatar asked Oct 16 '17 06:10

Krystian


People also ask

Why does decryption in AES take longer than encryption?

Bookmark this question. Show activity on this post. Fun fact: when using AES-NI for accelerating AES, decryption is actually slower because an additional instruction, AESIMC , must be used every round.

How long does it take to decrypt AES?

With the right quantum computer, AES-128 would take about 2.61*10^12 years to crack, while AES-256 would take 2.29*10^32 years. For reference, the universe is currently about 1.38×10^10 years old, so cracking AES-128 with a quantum computer would take about 200 times longer than the universe has existed.

Is AES encryption slow?

yes, it's slower, for sure. How much slower? That depends a lot on how much hardware help the operation is getting, CPUs can accelerate the process if all the ducks are in a row, so results can vary quite a bit. You will need to test in your environment to tell how fast it will be in your environment.

Which is faster AES encryption or AES decryption?

AES is a symmetric encryption, and is the same speed whether encrypting or decrypting.


2 Answers

You seem to be using SpongyCastle directly. SpongyCastle is the Android version of BouncyCastle (BC). BC however is a software only implementation of cryptographic algorithms and surrounding utility API's.

If you really want to speed up AES calculations you should be using the Java Security API instead, e.g. using the javax.crypto.Cipher class. This will allow hardware acceleration and native code execution on platforms that support it. Generally this will be all platforms as the main crypto functionality is implemented using OpenSSL libraries on the newer platforms.

Generally it is recommended to only use the Bouncy Castle "lightweight" API's (such as the software AES implementations you are using) whenever the required functionality is not available within the provided Cryptography providers. This is definitely not the case for algorithms such as AES/CBC.

Currently your library depends upon the byte code execution of the Bouncy Castle implementation, which is much slower. Note also that Bouncy Castle doesn't like debugging environments much, so make sure it runs without delays when testing the performance - if possible without debugger support.

like image 169
Maarten Bodewes Avatar answered Nov 16 '22 01:11

Maarten Bodewes


I have finally found a solution.

When I tried to create an issue on SpongyCastle GitHub I have noticed there are newer releases than 1.54... Well silly me for not investigating this earlier.

Just a word of caution, it didn't work straight away in my main project. The encryption/decryption mechanism is part of a library project which is then included in my main project. Please remember to also update your main project, or else it will still be very slow.

So it worked for me after:

  • changing the spongy castle version to 1.56
  • changing compileSdkVersion to 26
  • changing buildToolsVersion to 26.0.2
  • changing targetSdkVersion to 26

in both, library project and main project.

like image 40
Krystian Avatar answered Nov 16 '22 03:11

Krystian