Encryption

After trying and testing several encryption libraries, I finally found one that could be implemented in a way that would allow encryption and decryption of a byte array of any size (tested to an array with 255 characters).   Encryption using Spaniakos - AES Encryption Library for Arduino and Raspberry Pi.   Download library from: https://github.com/spaniakos/AES/archive/master.zip   See also: https://spaniakos.github.io/AES/index.html   https://www.arduinolab.net/aes-encryptiondecryption-using-arduino-uno/

 

//  Encryption example using Spaniakos - AES Encryption Library for Arduino and Raspberry Pi.
//  Example created by: Mark W Kiehl    Mechatronic Solutions LLC
//  Example provided "as-is" without any warranty or implied fitness for use. 

//////////////////////////////////////////////////////////////////////////////
//  Encryption using Spaniakos - AES Encryption Library for Arduino and Raspberry Pi
//  Download library from: https://github.com/spaniakos/AES/archive/master.zip
//  https://spaniakos.github.io/AES/index.html
//  https://www.arduinolab.net/aes-encryptiondecryption-using-arduino-uno/
#include 
AES aes;
byte *key = (unsigned char*)"01234567890123456789012345678901"; // encryption key
unsigned long long int myIv = 36753562; // CBC initialization vector; real iv = iv x2 ex: 01234567 = 0123456701234567
byte iv [N_BLOCK] ;
unsigned long successCount = 0;
boolean bVerbose = false;
// You must define arrays for encryption / decryption here globally 
// if you intend to populate the contents of strToEncrypt in a loop 
// where the contents change (such as sensor data).
// Define arrays for encryption
byte iSizeUnpadded = 111;
byte iSizePadded = 113; // =iSizeUnpadded+17 works for any size. See setup() for calculation of exact padding. 
byte arrToEncrypt[111]; // Size = iSizeUnpadded
byte cipher[113]; // Encrypted arrToEncrypt.  Size = iSizeUnpadded + 17
// Define arrays for decryption
byte arrDecryptedPadded[113]; // decrypted cipher with padding.  Size = iSizeUnpadded + 17
byte decrypted[111]; // decrypted string without padding.  Size = iSizeUnpadded
//////////////////////////////////////////////////////////////////////////////

const byte pinBuiltInLED = 13;

void setup() {
  pinMode(pinBuiltInLED, OUTPUT);
  
  Serial.begin(9600);
  while (!Serial) {
    delay(1);
  }
  Serial.println("Serial ready\n");

  // declare and initialize the variables for encryption / decryption
  aes.iv_inc();
  // Use the statement below to calculate the exact size for iSizePadded
  Serial.print("iSizePadded = "); Serial.println(sizeof(arrToEncrypt) + (N_BLOCK - ((sizeof(arrToEncrypt)-1) % 16)));

} // setup()


void loop() {

  digitalWrite(pinBuiltInLED, HIGH);
  
  // Fill arrToEncrypt with random content with a length between 5 and iSizeUnpadded
  byte iSizeArr = random(5,iSizeUnpadded);
  BuildRandomChar(arrToEncrypt, iSizeArr);
  int iSizePadded = iSizeArr + (N_BLOCK - ((iSizeArr-1) % 16)); // length of padded arrToEncrypt
  if (iSizePadded > sizeof(cipher) || iSizePadded > sizeof(arrDecryptedPadded)) {
    Serial.print("ERROR - array size of cipher or arrDecryptedPadded is too small!");
    while (1);
  }
  
  // Encrypt arrToEncrypt and update cipher with the result
  aesEncrypt(256, bVerbose);

  // Decrypt cipher, and update decrypted with the result
  aesDecrypt(256, bVerbose);
  
  // Compare arrToEncrypt to decrypted 
  int matches = 0;
  for(int i=0; i < iSizeUnpadded; i++){
    if(arrToEncrypt[i]==decrypted[i]){     
      matches++;  
    } 
  }
  if (matches == sizeof(arrToEncrypt)) {
    successCount++;
    digitalWrite(pinBuiltInLED, LOW); 
  }
  Serial.print(matches/sizeof(arrToEncrypt)*100);
  Serial.print("% match between arrToEncrypt and decrypted for size = ");
  Serial.print(iSizeArr); Serial.print(" bytes  ( encrypt/decrypt count = ");
  Serial.print(successCount); Serial.println(")  ");
  if (matches == sizeof(arrToEncrypt)) {
    successCount++;
  } else {
    Serial.print("ERROR after "); Serial.print(successCount); Serial.println(" encrypt/decrypt cycles");
    Serial.print("sizeof(arrToEncrypt) = "); Serial.println(sizeof(arrToEncrypt));
    Serial.print("matches = "); Serial.println(matches);
    for(int i=0; i < sizeof(arrToEncrypt); i++){
      Serial.print(i); Serial.print(",0x"); Serial.print(arrToEncrypt[i],HEX);
      Serial.print(",0x"); Serial.println(decrypted[i],HEX);
    }
    while (1);
  }
  Serial.println();
  
} // loop()

//////////////////////////////////////////////////////////////////////////////
//  Encryption using Spaniakos - AES Encryption Library for Arduino and Raspberry Pi

void aesDecrypt(int bits, boolean bVerbose) {
  // Decrypt cipher and write to arrDecryptedPadded
  aes.set_IV(myIv);
  aes.get_IV(iv);
  unsigned long us = micros();
  //Serial.print("aesDecrypt aes.get_size() = "); Serial.println(aes.get_size());
  aes.do_aes_decrypt(cipher,iSizeUnpadded+1,arrDecryptedPadded,key,bits,iv); 
  if (bVerbose == true) {
    Serial.print("Decryption took "); Serial.print(micros() - us); Serial.println(" us");  
  }
  // Create new array decrypted with the unencrypted content  
  // from arrDecryptedPadded excluding the padding. 
  for (int i=0; i < iSizeUnpadded; i++) {
    decrypted[i] = arrDecryptedPadded[i];
  } 
} // aesDecrypt()


void aesEncrypt(int bits, boolean bVerbose) {
  //  Encrypts arrToEncrypt based on bits (256) bit encryption and updates
  //  cipher with the encrypted result.   
  aes.set_IV(myIv);
  aes.get_IV(iv);
  unsigned long us = micros ();
  //Serial.print("aesEncrypt aes.get_size() = "); Serial.println(aes.get_size());
  aes.do_aes_encrypt(arrToEncrypt,iSizeUnpadded+1,cipher,key,bits,iv);
  if (bVerbose == true) {
    Serial.print("Encryption took "); Serial.print(micros() - us); Serial.println(" us");
  }
} // aesEncrypt()

//////////////////////////////////////////////////////////////////////////////

void BuildRandomChar(byte *arr, int len){
  byte j = 0;
  for (int i=0; i < len-1; i++) {
    switch (j){
      case 0:
        arr[i] = char(random(65,91));
        j = 1;
        break;
      case 1:
        arr[i] = char(random(97,123));
        j = 2;
        break;
      default:
        arr[i] = char(random(48,58));
        j = 0;
        break;
    } // switch
  }
  arr[len-1] = 0x00;
} // BuildRandomChar()

 


Do you need help developing or customizing a IoT product for your needs?   Send me an email requesting a free one hour phone / web share consultation.  

 

The information presented on this website is for the author's use only.   Use of this information by anyone other than the author is offered as guidelines and non-professional advice only.   No liability is assumed by the author or this web site.