AES encryption from Arduino to Android

I'm a little confused on what configuration I should use on the two libraries I am using from programming an Arduino and Android. I want to be able to:

  1. Create random string in Arduino
  2. Pass it to Android to encrypt with AES and shared secret key
  3. Pass back to Arduino to decrypt with AES and shared secret key
  4. Verify that original random string matches decrypted string

I am using this Arduino library and this Android library

My arduino code I set up to test encrypting an decrypting:

#include <AES.h>

AES aes ;

#define KEYLENGTH 32
char PassString[] = "This is hard to believe but true";
byte key[KEYLENGTH];

char Message[] = "Ncrypted Message";

byte plain[N_BLOCK];
byte cipher [N_BLOCK] ;
byte decrypted [N_BLOCK] ;

void setup() {
  Serial.begin(9600);
  Serial.println(F("Starting AES test"));
  
  // Pass the key into the byte array
  for (int i = 0; i < KEYLENGTH; i++) {
    key[i] = PassString[i];
  }
  
  if (aes.set_key (key, KEYLENGTH) !=0){
    Serial.println(F("Failed to set key"));
  }
}

void loop() {
  // Show original message
  Serial.print(F("Un-encrypted message: "));
  Serial.println(Message);
  Serial.println(F("Un-encrypted binary: "));
  for (int i = 0; i < N_BLOCK; i++) {
    plain[i] = Message[i];
    cipher[i] = 0;
    decrypted[i] = 0;
    Serial.print(plain[i]);
    Serial.print(F(" "));
  }
  Serial.println(F(""));
  
  // Show encrypted message
  if (aes.encrypt(plain, cipher) == 0) {
    Serial.println(F("encrypted: "));
    for (int i = 0; i < N_BLOCK; i++) {
      Serial.print(cipher[i]);
      Serial.print(F(" "));
    }
    Serial.println(F(""));
  } else {
    Serial.println(F("Failed to encrypt"));
  }
  
  // Show decrypted message
  if (aes.decrypt(cipher, decrypted) == 0) {
    Serial.println(F("decrypted binary: "));
    for (int i = 0; i < N_BLOCK; i++) {
      Serial.print(decrypted[i]);
      Serial.print(F(" "));
    }
    Serial.println(F(""));
    Serial.println(F("decrypted char: "));
    for (int i = 0; i < N_BLOCK; i++) {
      Serial.print(char(decrypted[i]));
    }
    Serial.println(F(""));
    
  } else {
    Serial.println(F("Failed to decrypt"));
  }
  
  
  Serial.println(F("AES test complete"));
  delay(100000);
  
}

My Android program is almost verbatim from the link above.

I can get both of them to encrypt and decrypt their own messages, but their set ups seem very different and haven't been able to encrypt each others. The Android code seems to have quite a bit more involved like creating keys and salts. Both libraries are pretty versatile and I'm not sure how to make them encrypt the same way.

I seem to be missing some basics concepts, but after all the researching I've done on encryption I've realized that this is one of the most confusing and difficult parts of my project! A push in the right direction would be very much appreciated.

I don't know either of the libraries you've mentioned but I take it you realise that there should be TWO keys. One does the encrypting, the other does the decrypting.

You can't use the same key to decrypt as you used to encrypt.

KenF:
I don't know either of the libraries you've mentioned but I take it you realise that there should be TWO keys. One does the encrypting, the other does the decrypting. You can't use the same key to decrypt as you used to encrypt.

AES is symmetric.

The Android library is using CBC block mode so you will need to

a) use the CBC mode on the Arduino
b) use a shared IV (Initialisation Vector)

For best security the IV should be a different random value (up to 16 bytes but padded to 16 bytes in any way you want) each time you encrypt. The IV does not need to be kept secret (only the key needs to be kept secret) so can be passed in the clear from the device doing the encryption to the device doing the decryption.

I have not used either of these libraries but it is likely that you will need to also use some form of reversible padding to make the cleartext length a multiple of 16 bytes. The most common padding is PKCS5 - Google is your friend.

I've got the my Arduino code using CBC now, but I still think I'm pretty far off. The Android implementation seems to do quite a bit more. I'm very new to AES (however, with all the reading I'm starting to understand a bit). Here is my new Arduino program:

#include <AES.h>

AES aes ;

byte key[] = 
{
  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
} ;

byte plain[] =
{
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
} ;

byte my_iv[] = 
{
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
} ;

char PassString[] = "This is hard to believe but true";
char Message[] = "We, the Fairies, blithe and antic Of dimensions not gigantic, Th";

byte cipher [4*N_BLOCK] ;
byte check [4*N_BLOCK] ;

int bits = 128;
int blocks = 4;

void loop () 
{}


void setup ()
{
  Serial.begin (9600) ;
  Serial.println ("Starting encryption...") ;

  byte iv [N_BLOCK] ;
  
  // Pass the key into the byte array
  for (int i = 0; i < 32; i++) {
    key[i] = PassString[i];
  }
  
  print_value ("KEY = ", key, 256) ;
  
  for (int i = 0; i < 64; i++) {
    plain[i] = Message[i];
  }
  
  // Set Key
  byte succ = aes.set_key (key, bits) ;
  
  // Encrypt
  for (byte i = 0 ; i < 16 ; i++)
    iv[i] = my_iv[i] ;
  succ = aes.cbc_encrypt (plain, cipher, blocks, iv) ;

  // Decrypt
  for (byte i = 0 ; i < 16 ; i++)
    iv[i] = my_iv[i] ;
  succ = aes.cbc_decrypt (cipher, check, blocks, iv) ;

  // Prints the plain, ciper, decrypted, and IV
  for (byte ph = 0 ; ph < (blocks == 1 ? 3 : 4) ; ph++)
  {
    for (byte i = 0 ; i < (ph < 3 ? blocks*N_BLOCK : N_BLOCK) ; i++)
    {
      byte val = ph == 0 ? plain[i] : ph == 1 ? cipher[i] : ph == 2 ? check[i] : iv[i] ;
      Serial.print (val>>4, HEX) ; Serial.print (val&15, HEX) ; Serial.print (" ") ;
    }
    Serial.println () ;
  }  

}

char * hex = "0123456789abcdef" ;
void print_value (char * str, byte * a, int bits)
{
  Serial.print (str) ;
  bits >>= 3 ; //bits goes from decimal 128 to decimal 16
  for (int i = 0 ; i < bits ; i++)
    {
      // of ex. 0xb9 prints b then 9
      byte b = a[i] ;
      Serial.print (hex [b >> 4]) ;
      Serial.print (hex [b & 15]) ;
    }
  Serial.println () ;
}

I have a few questions that hopefully will help me get this solved:

  • How do the "blocks" in the Arduino code relate to the Android implementation?
  • From what I've read, to decrypt the cipher text on the Arduino from Android I will need to send, the cipher text, the IV, and the PBE iteration count. Is that correct and everything?
  • Android code takes my key and uses a bunch of SecretKeys functions on it to I think randomize it and make it more secure. If I'm having to store the key on the Arduino, do I need to even bother with this?
  • Where is the PBE iteration count in the Arduino code? I don't really see anything in the library. Do I need to implement that myself? I saw in the "test_vectors" example of the library a section that had the following bit of code. Is this the iteration?
for (int j = 0 ; j < 1000 ; j++)
{
    succ = aes.encrypt (plain, cipher) ;
    aes.copy_n_bytes (plain, cipher, 16) ;
}

See my stackoverflow answer to question Arduino to Android secure bluetooth connection

Before using this nice library in my project I did some tests and would like to share with you the performance improvement from Arduino Uno to Teensy 3.1

Arduino Uno

Ready
N_BLOCK: 16
set_key 128 ->0 took 596us
encrypt ->0 took 1136us
decrypt ->0 took 1548us
plain:  6BC1BEE22E409F96E93D7E117393172A
key:    2B7E151628AED2A6ABF7158809CF4F3C
iv:     000102030405060708090A0B0C0D0E0F
enc:    7649ABAC8119B246CEE98E9B12E9197D
dec:    6BC1BEE22E409F96E93D7E117393172A

Teensy 3.1

Ready
N_BLOCK: 16
set_key 128 ->0 took 70us
encrypt ->0 took 173us
decrypt ->0 took 315us
plain:  6BC1BEE22E409F96E93D7E117393172A
key:    2B7E151628AED2A6ABF7158809CF4F3C
iv:     000102030405060708090A0B0C0D0E0F
enc:    7649ABAC8119B246CEE98E9B12E9197D
dec:    6BC1BEE22E409F96E93D7E117393172A