# Switching between AES and a highly performant algorithm

I want to de/encrypt several binary files rather frequently on a normally battery-powered device. My goal is to use AES-256 when the device is AC-powered and a highly performant algorithm when it's battery-powered to save power. I appreciate that the level of security will be compromised.

Is there a performant algorithm that provides "decent" security? I see that Blowfish fares a bit better according to this analysis, but the difference is rather small over AES-128. Given that the paper is almost 10 years old, are there good alternatives out there today?

Is AES-128 supposed to be the standard for something decently secured and highly performant?

• Do you have AES hardware on the device? AES-128 would be secure, but if you don't have hardware there are faster alternatives.
– otus
Sep 18 '15 at 8:12
• Yes, there is hardware support, but I was hoping for something to be even faster and less resource consuming. Would it make sense to use chacha though?
– Kar
Sep 18 '15 at 8:44
• You would have to benchmark it. Hardware implementations are often faster and less resource consuming, but ChaCha is less complex than AES so it could go either way.
– otus
Sep 18 '15 at 11:39
• If you're going to use a less-secure cipher when on battery, I strongly recommend you use it at all times. It would be trivial for an adversary to downgrade the security to the lowest level, so the higher one buys you nothing but complexity, and complexity is the enemy of security. Sep 18 '15 at 15:55
• +1 to @MrNerdHair. While "AES-256 is more secure than AES-128" is certainly true, that does not imply that AES-128 is insecure in any way. Using both does not make your app more secure (for the reasons he mentioned), it just creates more opportunities for security-reducing bugs. Sep 18 '15 at 16:32

Yes, AES-128 is intended to be the standard block cipher for building a secure and efficient symmetric cryptosystem using some block cipher operating mode, like CTR for encryption or GCM for authenticated encryption; efficiency can be particularly good when there is hardware support for AES and GCM.

There might be better choices in the case at hand, like for a 32-bit CPU ChaCha (perhaps combined with Poly1305 for authenticated encryption), or one of a plethora of lightweight block ciphers. If the device is 8-bit, and speed/efficiency paramount, one might even consider the deprecated and partially broken RC4, although its security is questionable even when discarding the beginning of the keystream.

Notice that keeping secret the key of either of these algorithm is hard in a non-security CPU assumed in the hands of an adversary, to the point of being best considered impossible facing a competent and determined adversary. And in a modern security CPU, you might have AES in hardware (thought often, optimized for security rather than speed).

• I don't think RC4 should be recommended when decent security is desired, especially if decent means "similar to AES-128".
– otus
Sep 18 '15 at 8:33
• Thanks. May I ask what you mean by keeping the key of is hard for ChaCha? How is it harder than AES?
– Kar
Sep 18 '15 at 10:59
• @Kar: I mean it is hard to keep a key (or anything) secret in a non-security IC; think JTAG probe.
– fgrieu
Sep 18 '15 at 11:34
• When security requirements aren't very high, ChaCha12 (i.e. ChaCha with 12 instead of 20 rounds) might be a good choice. Sep 18 '15 at 15:33
• @Kar Not to mention the power-consumption side-channel attacks. Sep 18 '15 at 15:53

For encryption or decryption of data that is encrypted on the fly, you can do that. For data you store you obviously have to use the same decryption, so if you encrypt a huge file using AES, you have to decrypt it using AES, even when on battery power.

First thing: If there is hardware support for AES, AES will be faster and using less power almost certain.

If you want to use a faster alternative, do the usual thing: look what people with bigger budgets for research and the same problem use.

I know what Google does for TLS. That's not exactly your use-case, but should be close enough. There are two blog posts I can recommend by Cloudflare and Google (images broken, shame on them).

I will summarize the corner points: Google was needing a fast and secure cipher that uses less power on mobile devices (say Android). They decided to use the ChaCha20 stream cipher with Poly1305 MAC.

It is included in Chrome since late 2013 and the google servers support it. Chrome prefers AES-GCM, if there is hardware support for it and else uses ChaCha20-Poly1305.

This seems like a good choice for you too and should be sufficiently secure. It was a finalist in eSTREAM and also is from djb, whom I hold in high regard as cryptographer.

Because it is in a similar security league as AES-128, you could also just use the faster of them, if you know the device. If you target multiple devices, I would go the Chrome way and switch between AES and ChaCha, depending on hardware support.

As you said you are OK with a little bit less security in the more performant algorithm, I suggest Speck for that. It was developed by the NSA, so although some might worry about a backdoor (I personally doubt there is one though I would not know the difference if there were), it probably also means that ordinary people will not break it easily if at all. Indeed it has been out 2 years and has been analyzed but not broken. It comes in a variety of key and block sizes. I actually have C++ code (maybe not the most optimized, but it does pass test vectors) for 32/64 (block size 32, key size 64) and for 128/128. Will post both in this answer. They are very fast and small.

32/64

#include "Speck.h"
#include <iostream>
#include <stdint.h>
using namespace std;

#define M 4
#define NUMBER_OF_ROUNDS 22
#define BIG_BIT_SHIFT 7
#define SMALL_BIT_SHIFT 2

#define ROR(x, r) ((x >> r) | (x << (16 - r)))
#define ROL(x, r) ((x << r) | (x >> (16 - r)))
#define R(x, y, k) (x = ROR(x, BIG_BIT_SHIFT), x += y, x ^= k, y = ROL(y, SMALL_BIT_SHIFT), y ^= x)
#define UNR(x, y, k) (y ^= x,y = ROR(y, SMALL_BIT_SHIFT),x ^= k,x -= y,x = ROL(x, BIG_BIT_SHIFT))

void Speck_32_64::generateRoundKeys(uint16_t *K, uint16_t *RK)
{
uint16_t keyChunks[M];
keyChunks[0] = K[0];
keyChunks[1] = K[1];
keyChunks[2] = K[2];
keyChunks[3] = K[3];

uint64_t i;
uint16_t indexer = 0;

for (i = 0; i < NUMBER_OF_ROUNDS; i++)
{
RK[i] = keyChunks[0];
indexer = 1 + i % (M-1);
R(keyChunks[indexer], keyChunks[0], i);
}
}

void Speck_32_64::encrypt(uint16_t *pt, uint16_t *ct, uint16_t *K)
{
uint64_t i, B = K[1], A = K[0];
ct[0] = pt[0]; ct[1] = pt[1];

uint16_t RK[NUMBER_OF_ROUNDS];
generateRoundKeys(K, RK);

for (i = 0; i < NUMBER_OF_ROUNDS; i++)
{
R(ct[1], ct[0], RK[i]);
}
}

void Speck_32_64::decrypt(uint16_t *pt, uint16_t *ct, uint16_t *K)
{
uint64_t i, B = K[1], A = K[0];
pt[0] = ct[0]; pt[1] = ct[1];

uint16_t RK[NUMBER_OF_ROUNDS];
generateRoundKeys(K, RK);
for (i = NUMBER_OF_ROUNDS; i > 0; i--)
{
UNR(pt[1], pt[0], RK[i - 1]);
}
}


128/128

#include "Speck.h"
#include <iostream>
#include <stdint.h>
using namespace std;

#define ROR(x, r) ((x >> r) | (x << (64 - r)))
#define ROL(x, r) ((x << r) | (x >> (64 - r)))
#define R(x, y, k) (x = ROR(x, 8), x += y, x ^= k, y = ROL(y, 3), y ^= x)
#define UNR(x, y, k) (y ^= x,y = ROR(y, 3),x ^= k,x -= y,x = ROL(x, 8))

void Speck_128_128::generateRoundKeys(uint64_t *K, uint64_t *RK)
{
uint64_t i, B = K[1], A = K[0];

for (i = 0; i < 32; i++)
{
RK[i] = A;
R(B, A, i);
}
}

void Speck_128_128::encrypt(uint64_t *pt, uint64_t *ct, uint64_t *K)
{
uint64_t i, B = K[1], A = K[0];
ct[0] = pt[0]; ct[1] = pt[1];

uint64_t RK[32];
generateRoundKeys(K, RK);

for (i = 0; i < 32; i++)
{
R(ct[1], ct[0], RK[i]);
}
}

void Speck_128_128::decrypt(uint64_t *pt, uint64_t *ct, uint64_t *K)
{
uint64_t i, B = K[1], A = K[0];
pt[0] = ct[0]; pt[1] = ct[1];

uint64_t RK[32];
generateRoundKeys(K, RK);
for (i = 32; i > 0; i--)
{
UNR(pt[1], pt[0], RK[i - 1]);
}
}

• Just going to add in the comment here that the header files are basic as can be. Each header file contains only a static class that holds prototypes of the methods.
– WDS
Sep 18 '15 at 8:42
• "It's always fascinating to study NSA-designed ciphers. I was particularly interested in the algorithms' similarity to Threefish, and how they improved on what we did. I was most impressed with their key schedule. I am always impressed with how the NSA does key schedules. And I enjoyed the discussion of requirements. Missing, of course, is any cryptanalytic analysis.": Bruce Schneier. There is a plethora of lightweight ciphers. I only found one paper describing the security of the ciphers, and the cipher is published by the NSA. I don't expect it to broken, but I leaves some questions.... Sep 18 '15 at 12:22
• @MaartenBodewes Yes, Schneier's blog is where I found Speck, and I noted the same quote you posted. I did not originally feel confident in it because of the NSA connection. However if you read further down in his blog, in the comments, you will notice Schneier expressing doubt any backdoor (if there was one) could remain hidden for long. As for papers on the security of Speck, see eprint.iacr.org/2014/320.pdf and citeseerx.ist.psu.edu/viewdoc/…. Both are attacks on reduced round variants. Full specification Speck is unbroken.
– WDS
Sep 18 '15 at 17:30

The best solution depends on the details of your application, but I have one comment and one suggestion.

First the comment: You say you have AES hardware available. I don't know the details of your platform, but this hardware is likely to be much more efficient in time/power than a software implementation of any reasonable encryption algorithm. You need to do some analysis/benchmarking here.

Now a suggestion that may work (depending on your particular application): If The amount of data that you need to encrypt while on battery power is fairly small, you can use pre-computation while on AC power to help. For example, while on AC power you can AES encrypt a nonce/counter and store the result. Then in battery mode you can xor these results with your plaintexts. So you are effectively implementing AES in CTR mode, but the only operation you need to perform on battery power is an xor.

The above is just an example to get you to think about application-specific alternatives. Perhaps if you share more details about your application you may get better suggestions.

• If you have AES in hardware, the RAM (or flash) access to load the XOR pad might cost similar power to just doing the AES. Not sure about that, though. Sep 19 '15 at 4:40