Hi guys, I would like to share my article about doing AES encryption in Arduino C++ and decrypt in C#. Feel free to check it out at the following blog/article, cheers.
https://www.codeproject.com/Articles/5365769/AES-Encrypted-Data-Transmission-between-Arduino-ES
or
in a nutshell, AES encryption algorithm works the same across any programming languages, you just need to set the same parameters at both side, then the encrypt and decrypt results will be same.
AES parameters:
- Cipher Mode
- Block/Key size (128 bits, 192 bits, 256 bits)
- Key bytes
- IV bytes (Initial Vector)
- Padding Mode
Here are 2 of the libraries that I used in the arduino encryption process.
1st, AESLib - AES Encryption, provided by Matej Sychra.
2nd, base64_encode, provided by dojyorin.
- Arthor’s Github: GitHub - dojyorin/arduino_base64: Convert between binary and base64 encoded string.
Here is a quick example:
Encryption in Arduino C++:
// import AES encryption library
#include "AESLib.h"
// import base64 conversion library
#include "arduino_base64.hpp"
// declare a global AESLib object
AESLib aesLib;
// the text encryption function
String encrypt(String inputText) {
// calculate the length of bytes of the input text
// an extra of byte must be added for a null character
// a null character will be filled as a text terminator
// so that the process will not overflow to other parts of memory
int bytesInputLength = inputText.length() + 1;
// declare an empty byte array (a memory storage)
byte bytesInput[bytesInputLength];
// convert the text into bytes, a null char is filled at the end
inputText.getBytes(bytesInput, bytesInputLength);
// calculate the length of bytes after encryption done
int outputLength = aesLib.get_cipher_length(bytesInputLength);
// declare an empty byte array (a memory storage)
byte bytesEncrypted[outputLength];
// initializing AES engine
// Cipher Mode and Key Size are preset in AESLib
// Cipher Mode = CBC
// Key Size = 128
// declare the KEY and IV
byte aesKey[] = { 23, 45, 56, 67, 67, 87, 98, 12, 32, 34, 45, 56, 67, 87, 65, 5 };
byte aesIv[] = { 123, 43, 46, 89, 29, 187, 58, 213, 78, 50, 19, 106, 205, 1, 5, 7 };
// set the padding mode to paddingMode.CMS
aesLib.set_paddingmode((paddingMode)0);
// encrypt the bytes in "bytesInput" and store the output at "bytesEncrypted"
// param 1 = the source bytes to be encrypted
// param 2 = the length of source bytes
// param 3 = the destination of encrypted bytes that will be saved
// param 4 = KEY
// param 5 = the length of KEY bytes (16)
// param 6 = IV
aesLib.encrypt(bytesInput, bytesInputLength, bytesEncrypted, aesKey, 16, aesIv);
// declare a empty char array
char base64EncodedOutput[base64::encodeLength(outputLength)];
// convert the encrypted bytes into base64 string "base64EncodedOutput"
base64::encode(bytesEncrypted, outputLength, base64EncodedOutput);
// convert the encoded base64 char array into string
return String(base64EncodedOutput);
}
Here's a quick example of decryption in C#:
public static string AesDecrypt(string base64str)
{
byte[] data = null;
// the base64 string into bytes that's encrypted at Arduino
byte[] encryptedData = Convert.FromBase64String(base64str);
// initialize AES encryption
using (Aes aes = Aes.Create())
{
// set the AES parameters
aes.KeySize = 128;
aes.BlockSize = 128;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
aes.Key = aesKey;
aes.IV = aesIv;
// Create a decryptor to decrypt the data
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
// initialize memory stream to read data from the encrypted bytes
using (MemoryStream msDecrypt = new MemoryStream(encryptedData))
{
// initialize the AES decryption engine
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
// declare a memory stream for AES to save the decrypted data
using (MemoryStream originalMemoryStream = new MemoryStream())
{
byte[] buffer = new byte[1024];
int readBytes;
while ((readBytes = csDecrypt.Read(buffer, 0, buffer.Length)) > 0)
{
originalMemoryStream.Write(buffer, 0, readBytes);
}
// extract the decrypted data from the memory stream
data = originalMemoryStream.ToArray();
}
}
}
}
// Convert the bytes into string
string text = System.Text.Encoding.UTF8.GetString(data);
// remove the last null character (added by Arduino as line terminator)
text = text.Remove(text.Length - 1, 1);
return text;
}