last updated: 2023-01-26
Song of this chapter: The Beatles > Please Please Me > Do You Want To Know A Secret
Because of the EU Energy Efficiency Directive from 2012 the gas and electricity Distribution System Operators (DSO) in Luxembourg replaced there gas and energy meters with smartmeters (named smarty
:(). Besides gas and electricity metering, the system is open for other metering data like water and district heat (M-Bus).
The French group Sagemcom delivered the smartmeters. All meters have to be read by one national central system, operated by a common operator. This is an economic group of interest (G.I.E.) of the 7 Luxembourgian gas and electricity DSO‘s named Luxmetering G.I.E..
Luxmetering is getting the data from 4 registers for active, reactive, import and export energy (4 times per hour) and the 3 registers for gas, water & heat (once per hour) over Power Line Communication (PLC
). The smartmeters have also alarms and logs for quality of electrical energy supply (voltage, outages,...) and fraud detection, and calendar functions for the 2 external relays (home applications).
The customer wants to get his data and this is possible by reading the blinking LED of the Smartmeter. Another possibility is the 10 second data from the Smartmeter P1
port (RJ12 connector under the green lid). The P1 data output communication protocol and format is specified in the Dutch Smart Meter Requirements v5.0.2 . The solution deployed in Luxembourg includes an additional security layer standard that is conform to the IDIS package 2.0 requirement.
The encryption layer is based on Device Language Message Specification (DLMS) security suite 0 algorithm: AES128-GCM
. More information can be found in this document.
We want to learn how to encrypt and decrypt our data in a safe way and Galois Counter Mode (GCM
) in combination with the Advanced Encryption Standard (AES
) block cipher used by the smartmeters is a good starting point.
There are 3 properties we want for securing our data:
Confidentiality
:
Nobody should be able to discover the plaintext message, or information about the plaintext message.
Integrity
:
Nobody should be able to modify the message without the legitimate users noticing.
Authenticity
:
The ability to prove that it is our message and to prevent forgery of new messages (usually provided via a Message Authentication Code MAC
). Authenticity automatically implies integrity.
AES
with Galois/Counter Mode (GCM
) block mode provides all the 3 properties from above.
AES
is a specification for the encryption of electronic data. AES-128
works with a key size of 128 bits (there exist three standard key sizes (128, 192 and 256 bits)). The fixed block size for AES is always 128 bits.
GCM
is a mode of operation for symmetric-key cryptographic block ciphers that has been widely adopted because of its efficiency and performance. GCM
is defined for block ciphers with a block size of 128 bit.
GCM
can be realised with our Arduino or ESP boards because it does not need powerful hardware. The throughput rates allow high-speed communication. GCM
provides both data authenticity (integrity) and confidentiality.
In GCM
data blocks are numbered sequentially (counter), and then this block number is combined with an Initialization Vector (IV
) and encrypted with a block cipher E
, usually AES-128
.
For authenticated encryption we need four inputs:
A secret Key K
with an appropriate length. With AES-128
the key is 128 bits long (16 byte).
An Initialisation Vector IV
with a length between 1-264 bits. Often 96 bits (12 byte) are used (enough secure and efficient). Counter modes are stream ciphers, and it is essential that a different IV
is used for each stream that is encrypted. So its logical to add the changing counter to the vector.
The Plaintext P
.
Additional Authenticated Data (AAD
) A
. This additional data is not encrypted and not included in the encrypted output. The aim of AAD is to attach information to the ciphertext that cannot be changed or separated. The data is validated by verification of the authentication tag (see below). The first byte of AAD is called security control and indicates the level of security to use.
After the encryption we get two outputs:
The Ciphertext C
.
An Authentication Tag T
with a length between 0 and 128 bits.
These are combined with the Additional Authenticated Data AAD
and the Initialisation Vector IV
, because this information is needed for the decryption.
To be able to decrypt the message, we need the Initialisation Vector IV
, the Ciphertext C
, the authentication Tag T
, the Additional Authenticated Data (AAD) A
and the Key K
. So we get five inputs, but only one output, the Plaintext P
(or an error message if the decryption wasn't successful).
In the following picture we see the output of a Smartmeter P1 port. The port uses inverted TIA-232
, and the serial stream is encrypted with AES128-GCM
:
As the receiver needs the Initialization Vector (IV
) to decrypt the message, we can retrieve it from the message. It has has 12 byte and is composed of 8 byte referenced as system title beginning with the text "SAGgp" and the counter of 4 byte. It should be random or pseudorandom. In our case the IV is not really random but only non-repeating (number used once called a nonce).
The Cyphertext C
begins after the Counter and ends 12 byte before the end of the message.
The authentication tag T
(12 byte) is appended to the message.
The Additional Authenticated Data (AAD) A
for Luxembourgish Smartmeter has 1+16 byte and is 0x3000112233445566778899AABBCCDDEEFF
, 0x30 being the security control byte.
The Key K
(16 byte) is provided by your DSO
(e.g. CREOS) or Luxmetering
.
We need the amazing Arduino Cryptography Library from Rhys Weatherley. It is called Crypto
. Install it with the Arduino library manager (Tools > Manage Libraries... ; search for Crypto). To use the library we include the following heqader-files:
+
#include <Crypto.h>
#include <AES.h>
#include <GCM.h>
GCM
-Tag. 0xDB, 0x08, 0x53, 0x41, 0x47, 0x67, 0x70, 0x01, 0x5B, 0xEB, 0x82, 0x02,
0x7A, 0x30, 0x00, 0x04, 0xE9, 0x14, 0x06, 0xF4, 0x36, 0x4C, 0x43, 0xBB,
...
0x60, 0xDD, 0xC9, 0xD2, 0x67, 0x0E, 0xD0, 0xCB, 0x31, 0x15, 0x37, 0x8C,
0x4E, 0xCD, 0x9A, 0xF6, 0x8D, 0x05, 0x2C, 0xD8, 0x97, 0x94, 0x26, 0x39
The 16 byte encryption key for this meter (SAG1030700089067) is AEBD21B769A6D13C0DF064E383682EFF
. The AAD
is fix: 0x3000112233445566778899AABBCCDDEEFF
. Add the 16 byte encryption key, the GCM
-Tag, the IV
and the AAD
to the following program (bytes in hex, separated by commas) and test it. Document the serial monitor output. If you use an ESP8266 or ESP32 you have to uncomment the line //#define ESP
.
// iot_jdi_Encrytion_1_decrypt_AES128_GCM_smarty.ino
// weigu.lu
// you need the crypto library. Install it in Arduino (Manage libraries)
#include <Crypto.h>
#include <AES.h>
#include <GCM.h>
#define MAX_PLAINTEXT_LEN 620
struct Vector_GCM {
const char *name;
byte keysize;
unsigned int datasize;
byte authsize;
byte ivsize;
byte tagsize;
uint8_t key[16];
byte plaintext[MAX_PLAINTEXT_LEN];
byte ciphertext[MAX_PLAINTEXT_LEN];
byte authdata[17];
byte iv[12];
byte tag[12];
};
static Vector_GCM const testVectorGCM PROGMEM = {
.name = "AES-128 GCM",
.keysize = 16,
.datasize = 617,
.authsize = 17,
.ivsize = 12,
.tagsize = 12,
.key = {},
.plaintext = {},
.ciphertext = {0x06, 0xF4, 0x36, 0x4C, 0x43, 0xBB, 0x04, 0xA1, 0x3E, 0xE9, 0xBC, 0x0E,
0xBE, 0x1F, 0x92, 0xA0, 0x1B, 0x5E, 0x02, 0x12, 0x93, 0x1F, 0x32, 0x63,
0xB5, 0xE6, 0x37, 0x15, 0x2D, 0x77, 0x59, 0x86, 0x53, 0x18, 0x60, 0x5B,
0xAD, 0xF8, 0xB4, 0xE1, 0x2F, 0x74, 0xF0, 0xE8, 0xD9, 0x4C, 0xC3, 0xD3,
0xED, 0x77, 0x9A, 0x69, 0x15, 0x13, 0x65, 0xA8, 0x72, 0x5B, 0x49, 0xD5,
0x1D, 0x77, 0x33, 0x2C, 0xE2, 0x83, 0xF7, 0x67, 0xA9, 0x7C, 0x93, 0xA6,
0x74, 0xEF, 0xEF, 0x40, 0x2D, 0x21, 0x30, 0x0E, 0xDC, 0x8A, 0xBC, 0x1F,
0x52, 0x16, 0xD2, 0xBD, 0x4E, 0xC9, 0x18, 0xA8, 0x62, 0xE7, 0xAC, 0xFD,
0x1F, 0x07, 0x38, 0xCD, 0x3F, 0xDE, 0xF7, 0xC8, 0xBF, 0xA3, 0x51, 0xD6,
0x2C, 0xE0, 0xBF, 0x5A, 0x0C, 0x68, 0xC6, 0x81, 0xA1, 0xF9, 0x00, 0x43,
0xE3, 0x1C, 0x66, 0x44, 0x9B, 0x20, 0x9D, 0x19, 0x3C, 0x48, 0xB0, 0xA4,
0x8D, 0x8C, 0x2A, 0x1F, 0x3B, 0xB0, 0xEF, 0xE2, 0x5B, 0xA6, 0x5E, 0x7C,
0x35, 0x66, 0x5E, 0x26, 0x53, 0x51, 0x0E, 0x47, 0xB0, 0x28, 0x73, 0x79,
0x04, 0xB7, 0x75, 0xC0, 0x80, 0xEA, 0xB8, 0x29, 0x32, 0xC3, 0x2B, 0x9B,
0xCB, 0x09, 0x62, 0xFE, 0x16, 0x86, 0x26, 0x24, 0xAA, 0x1F, 0x2E, 0xC8,
0xEB, 0x8F, 0x3D, 0xB1, 0x65, 0x82, 0x6C, 0x14, 0x09, 0x05, 0xB5, 0xE6,
0x23, 0x52, 0x73, 0x24, 0xF2, 0xE2, 0x5A, 0x35, 0x7B, 0x99, 0xE7, 0x32,
0x05, 0xD8, 0xA8, 0xD2, 0x99, 0xC9, 0x7D, 0x2D, 0x8F, 0x34, 0xDA, 0x52,
0x41, 0x27, 0x35, 0x4B, 0x6B, 0x13, 0xBF, 0x70, 0x86, 0x79, 0xEA, 0x26,
0x38, 0x3B, 0x56, 0x21, 0xED, 0xB6, 0x89, 0xC4, 0x01, 0x8C, 0x9E, 0x72,
0x4A, 0xC2, 0xA4, 0xE3, 0xD0, 0xF1, 0x37, 0x0C, 0x3A, 0xC4, 0x6E, 0x17,
0x32, 0x57, 0x7D, 0x32, 0xFD, 0x5D, 0x6B, 0x18, 0x9A, 0xC1, 0x5E, 0x74,
0x15, 0x37, 0x6C, 0xE8, 0x87, 0xCD, 0x52, 0xC8, 0x80, 0xA1, 0x42, 0xC0,
0x23, 0x0C, 0x21, 0xFA, 0xCE, 0x9F, 0x95, 0xAB, 0x18, 0xFB, 0xBB, 0x92,
0xC9, 0xE1, 0xF4, 0xD2, 0xE5, 0xC2, 0x22, 0x03, 0x72, 0xF2, 0x40, 0xFF,
0x3B, 0x39, 0xB6, 0x75, 0xE1, 0x5A, 0x2B, 0xBA, 0x4D, 0x6F, 0x4A, 0x7A,
0xEE, 0x55, 0x1C, 0xC4, 0x5B, 0x11, 0x22, 0x0F, 0x3A, 0x0E, 0xF8, 0x20,
0x72, 0x08, 0x92, 0x59, 0x56, 0xC1, 0x7E, 0xF3, 0xF4, 0x18, 0x1F, 0xFD,
0xAC, 0x8C, 0x47, 0x82, 0x56, 0xF2, 0x72, 0x23, 0x92, 0x3D, 0xAC, 0xA7,
0x06, 0x58, 0x52, 0x63, 0xF4, 0x41, 0xBC, 0x15, 0x1B, 0xC8, 0x1D, 0xAE,
0x0E, 0xDE, 0x9B, 0x35, 0x78, 0x19, 0x17, 0x3D, 0x95, 0x72, 0x09, 0x85,
0x44, 0x90, 0x9C, 0x3A, 0xEE, 0xF2, 0x11, 0x29, 0x85, 0x40, 0xB6, 0x47,
0x2F, 0x92, 0x4D, 0x35, 0x29, 0x05, 0x58, 0x4A, 0x68, 0x7E, 0xBA, 0x2D,
0x71, 0xEC, 0x3C, 0x9B, 0x7A, 0x87, 0x37, 0x1E, 0x0C, 0xF0, 0x78, 0xE3,
0xC9, 0x18, 0xD3, 0x47, 0xEA, 0xF3, 0x7E, 0x9F, 0x76, 0x0B, 0x5F, 0x32,
0x88, 0xF3, 0x8F, 0xE3, 0x64, 0x92, 0xBB, 0x13, 0x2C, 0x86, 0x82, 0x2D,
0x32, 0x8E, 0xF6, 0x20, 0x30, 0xA5, 0xBE, 0x23, 0x9A, 0x25, 0x3D, 0x48,
0x82, 0xBE, 0xA2, 0xC1, 0xEA, 0x53, 0xB9, 0xAF, 0x64, 0x58, 0x3E, 0x9B,
0x2A, 0x47, 0xC2, 0x82, 0x7B, 0x95, 0x87, 0xE9, 0xE2, 0x4F, 0x03, 0xC5,
0xAC, 0xAD, 0x09, 0x21, 0x1F, 0x3C, 0x30, 0x70, 0x4E, 0xFD, 0xE8, 0x03,
0xEF, 0xCD, 0x86, 0x82, 0x1C, 0xBE, 0x7D, 0xEE, 0x92, 0x95, 0x73, 0x76,
0x65, 0xA4, 0xA9, 0xBF, 0x48, 0xD0, 0x10, 0x0D, 0xD2, 0xC6, 0x84, 0x88,
0x18, 0x28, 0xFA, 0xD3, 0x76, 0x6F, 0x96, 0xA6, 0xCE, 0x0E, 0xF2, 0xE3,
0xF9, 0xF3, 0xEA, 0x4A, 0x20, 0x7C, 0x54, 0x45, 0xB2, 0xCE, 0x5C, 0x47,
0xF5, 0xDB, 0x98, 0x3B, 0xE5, 0x46, 0x11, 0xCF, 0xD9, 0x94, 0xC5, 0xEC,
0x48, 0x3B, 0x16, 0x7C, 0x2E, 0x8F, 0xC3, 0x42, 0xD5, 0xA9, 0x06, 0x8F,
0x76, 0x67, 0x61, 0x9C, 0x1F, 0xA4, 0xF2, 0x03, 0x38, 0x6E, 0xED, 0x54,
0x14, 0x9F, 0x5B, 0x11, 0x09, 0x8C, 0x9C, 0xCC, 0xB0, 0xF2, 0xEC, 0x66,
0xCB, 0x5D, 0x15, 0x44, 0xA0, 0x1E, 0xCB, 0x01, 0x74, 0x06, 0xE7, 0x67,
0x81, 0x85, 0x17, 0x3E, 0xD2, 0x80, 0x9E, 0xD6, 0xBB, 0x10, 0x92, 0xBB,
0xC3, 0xCB, 0xA4, 0x0B, 0xEA, 0x60, 0xDD, 0xC9, 0xD2, 0x67, 0x0E, 0xD0,
0xCB, 0x31, 0x15, 0x37, 0x8C},
.authdata = {},
.iv = {},
.tag = {},
};
Vector_GCM my_vector;
void setup() {
Serial.begin(115200);
while(!Serial); // Wait for USB
Serial.println("Decrypted Text:\n");
/****** copy data to vector ******/
memcpy_P(&my_vector, &testVectorGCM, sizeof(Vector_GCM));
/****** decrypt ******/
decrypt_text(my_vector);
delay(500);
for (unsigned int i=0; i<my_vector.datasize; i++) {
Serial.write(my_vector.plaintext[i]);
}
}
void loop() {}
void decrypt_text(Vector_GCM &vect) {
GCM<AES128> *gcmaes128 = 0;
gcmaes128 = new GCM<AES128>();
gcmaes128->setKey(vect.key, gcmaes128->keySize());
gcmaes128->setIV(vect.iv, vect.ivsize);
gcmaes128->decrypt(vect.plaintext, vect.ciphertext, vect.datasize);
delete gcmaes128;
}
Wire an Arduino board (Leonardo, Mega or Teensy, Serial1) and an ESP32 board (Serial2), so they can talk together via TIA-232
. Pay attention to the different voltage levels! Draw the circuit and do the connections.
Write two sketches, so that the Arduino board sends "UHU
" and the the ESP32 returns "HAI
". Document the sketches.
Acquire an oscilloscope screen picture of a "man-in-the-middle" attack, containing the 3 bytes. Decipher the texts on the oscilloscope picture.
Tip: Include a 1 ms delay in your main loop to better trigger the data stream.
In the following program we see how we can encrypt and decrypt a text with the Arduino Crypto library in AES128-GCM
. Create two sketches based on this program, so that a serial communication between the Arduino (Serial1) and the ESP32 (Serial 2) is encrypted and decrypted in one direction. Use a method similar to that used by the Smartmeter, meaning IV and Tag must be added to the message. The IV can be fixed (no counter). Document the sketches and the outputs (Serial stream of sender and receiver and the decoded text (receiver) in the Serial Monitor).
// iot_jdi_Encryption_3_encrypt_decrypt_GCM128.ino
// weigu.lu
// you need the crypto library. Install it in Arduino (Manage libraries)
#include <Crypto.h>
#include <AES.h>
#include <GCM.h>
const unsigned int MAX_PLAINTEXT_LEN = 100;
// Text to encrypt:
const char mytext[MAX_PLAINTEXT_LEN] = "HAI";
const char myvname[] = "AES-128 GCM"; // vector name
char mykey[] = "AEBD21B769A6D13C0DF064E383682EFF"; // Key for SAG1030700089067 (16 byte)
char myAAD[] = "3000112233445566778899AABBCCDDEEFF"; // 17 byte (in Hex 34 character)
char myIV[] = "53414767700067C800000000"; // "SAGgp + "0x0067C8" + 4 byte counter
struct Vector_GCM {
const char *name;
static const byte keysize = 16;
unsigned int datasize;
static const byte authsize = 17;
static const byte ivsize = 12;
static const byte tagsize = 12;
byte key[keysize];
byte plaintext[MAX_PLAINTEXT_LEN];
byte ciphertext[MAX_PLAINTEXT_LEN];
byte authdata[authsize];
byte iv[ivsize];
byte tag[tagsize];
};
unsigned long counter = 0;
Vector_GCM my_vector;
void setup() {
Serial.begin(115200);
delay(2500);
Serial.println("\nSerial ok");
// initialise the vector
if (init_vector_GCM_encryption(my_vector, myvname, mykey, mytext, myAAD, myIV) != 0) {
Serial.println("Error while initialising vector: ");
}
print_vector(my_vector);
delay(2500);
}
void loop() {
/****** encrypt ******/
encrypt_text(my_vector);
//print_vector(my_vector);
Serial.print("IV: ");
for (byte i=0; i<my_vector.ivsize; i++) {
Serial.print(my_vector.iv[i],HEX);
}
Serial.print(" GCM-tag: ");
for (byte i=0; i<my_vector.tagsize; i++) {
Serial.print(my_vector.tag[i],HEX);
}
Serial.print(" Encrypted text: \"");
for (unsigned int i=0; i<my_vector.datasize; i++) {
Serial.print(my_vector.ciphertext[i],HEX);
}
Serial.println("\"");
/****** clear the plaintext ******/
for (int i=0; i<MAX_PLAINTEXT_LEN; i++) {
my_vector.plaintext[i] = 0;
}
//print_vector(my_vector);
/****** decrypt ******/
decrypt_text(my_vector);
//print_vector(my_vector);
Serial.print( "The decrypted text is: \"");
for (unsigned int i=0; i<my_vector.datasize; i++) {
Serial.write(my_vector.plaintext[i]);
}
Serial.println("\"");
/****** increment counter and cook new text ******/
increment_counter(my_vector, counter);
cook_new_text(my_vector, mytext);
delay(3000);
}
// initialize the vector_structure from c-strings
int init_vector_GCM_encryption(Vector_GCM &vect, const char *vect_name, char *key,
const char *plaintext, char *aad, char *iv) {
if (strlen(key) != (vect.keysize*2)) {
Serial.println("Key must have " + String(vect.keysize) + " bytes");
return -1;
}
if (strlen(aad) != (vect.authsize*2)) {
Serial.println("AAD must have " + String(vect.authsize) + " bytes");
return -1;
}
if (strlen(iv) != (vect.ivsize*2)) {
Serial.println("IV must have " + String(vect.ivsize) + " bytes");
return -1;
}
vect.name = vect_name; // init vector name
c_string_hexbytes_2_bytes(key, vect.key); // array passed by ref
vect.datasize = strlen(plaintext); // init plaintext
for (unsigned int i=0; i<vect.datasize; i++) {
vect.plaintext[i] = mytext[i];
yield();
}
c_string_hexbytes_2_bytes(aad, vect.authdata); // array passed by ref
c_string_hexbytes_2_bytes(iv, vect.iv); // array passed by ref
return 0;
}
void encrypt_text(Vector_GCM &vect) {
GCM<AES128> *gcmaes128 = 0;
gcmaes128 = new GCM<AES128>();
gcmaes128->setKey(vect.key, gcmaes128->keySize());
gcmaes128->setIV(vect.iv, vect.ivsize);
gcmaes128->encrypt(vect.ciphertext, vect.plaintext, vect.datasize);
gcmaes128->computeTag(vect.tag, vect.tagsize);
delete gcmaes128;
}
void decrypt_text(Vector_GCM &vect) {
GCM<AES128> *gcmaes128 = 0;
gcmaes128 = new GCM<AES128>();
gcmaes128->setKey(vect.key, gcmaes128->keySize());
gcmaes128->setIV(vect.iv, vect.ivsize);
gcmaes128->decrypt(vect.plaintext, vect.ciphertext, vect.datasize);
delete gcmaes128;
}
void increment_counter(Vector_GCM &vect, unsigned long &counter) {
unsigned long counter_high, counter_low;
counter++;
counter_high = counter / 65536;
counter_low = counter % 65536;
vect.iv[8] = highByte(counter_high);
vect.iv[9] = lowByte(counter_high);
vect.iv[10] = highByte(counter_low);
vect.iv[11] = lowByte(counter_low);
}
void cook_new_text(Vector_GCM &vect, const char mytext[]) {
String new_text(mytext);
new_text = new_text + "_" + counter;
vect.datasize = strlen(new_text.c_str()); // init new plaintext
for (unsigned int i=0; i<vect.datasize; i++) {
vect.plaintext[i] = new_text.c_str()[i];
}
}
/****** Helper functions ******/
// convert a c-string with hexbytes to real bytes
int c_string_hexbytes_2_bytes(char c_string[], byte byte_array[]) {
byte tmp_array_size = strlen(c_string);
byte tmp_array[tmp_array_size];
for (byte i=0; i<tmp_array_size; i++) {
if ((c_string[i]>='A') && (c_string[i]<='F')) tmp_array[i] = byte(c_string[i]-55);
else if ((c_string[i]>='a') && (c_string[i]<='f')) tmp_array[i] = byte(c_string[i]-87);
else if ((c_string[i]>='0') && (c_string[i]<='9')) tmp_array[i] = byte(c_string[i]-48);
else {
Serial.println("error: no Hex bytes in string");
return -1;
}
if (i%2==1) { // i odd (every second character)
byte_array[(i-1)/2] = byte((tmp_array[i-1]*16)+tmp_array[i]);
}
}
return 0;
}
void print_vector(Vector_GCM &vect) {
const byte MAX_SCREEN_LINE_LENGTH = 25;
Serial.print("-----------------------------------\nPrint Vector: ");
Serial.print("\nVector_Name: " + String(vect.name));
Serial.print("\nKey Size: " + String(vect.keysize));
Serial.print("\nData Size: " + String(vect.datasize));
Serial.print("\nAuth_Data Size: " + String(vect.authsize));
Serial.print("\nInit_Vect Size: " + String(vect.ivsize));
Serial.print("\nAuth_Tag Size: " + String(vect.tagsize));
Serial.print("\nKey: ");
for(byte i=0; i<vect.keysize; i++) {
Serial.print(String(vect.key[i],HEX) + ' ');
}
Serial.print("\nPlaintext: ");
byte more_lines = (vect.datasize/MAX_SCREEN_LINE_LENGTH);
if (more_lines) {
for(byte i=0; i<more_lines; i++) {
for(byte j=0; j<MAX_SCREEN_LINE_LENGTH;j++) {
Serial.print(String(vect.plaintext[i*MAX_SCREEN_LINE_LENGTH+j],HEX) + ' ');
yield();
}
Serial.println();
}
}
for(byte j=0; j<(vect.datasize%MAX_SCREEN_LINE_LENGTH);j++) {
Serial.print(String(vect.plaintext[more_lines*MAX_SCREEN_LINE_LENGTH+j],HEX) + ' ');
yield();
}
Serial.print("\nCyphertext: ");
if (more_lines) {
for(byte i=0; i<more_lines; i++) {
for(byte j=0; j<MAX_SCREEN_LINE_LENGTH;j++) {
Serial.print(String(vect.ciphertext[i*MAX_SCREEN_LINE_LENGTH+j],HEX) + ' ');
yield();
}
Serial.println();
}
}
for(byte j=0; j<(vect.datasize%MAX_SCREEN_LINE_LENGTH);j++) {
Serial.print(String(vect.ciphertext[more_lines*MAX_SCREEN_LINE_LENGTH+j],HEX) + ' ');
yield();
}
Serial.print("\nAuth_Data: ");
for(byte i=0; i<vect.authsize; i++) {
Serial.print(String(vect.authdata[i],HEX) + ' ');
}
Serial.print("\nInit_Vect: ");
for(byte i=0; i<vect.ivsize; i++) {
Serial.print(String(vect.iv[i],HEX) + ' ');
}
Serial.print("\nAuth_Tag: ");
for(byte i=0; i<vect.tagsize; i++) {
Serial.print(String(vect.tag[i],HEX) + ' ');
}
Serial.println("\n-----------------------------------");
}
```
`OUTPUT:`
```bash
Serial ok
`-----------------------------------`
Print Vector:
Vector_Name: AES-128 GCM
Key Size: 16
Data Size: 3
Auth_Data Size: 17
Init_Vect Size: 12
Auth_Tag Size: 12
Key: ae bd 21 b7 69 a6 d1 3c d f0 64 e3 83 68 2e ff
Plaintext: 48 41 49
Cyphertext: 0 0 0
Auth_Data: 30 0 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff
Init_Vect: 53 41 47 67 70 0 67 c8 0 0 0 0
Auth_Tag: 0 0 0 0 0 0 0 0 0 0 0 0
`-----------------------------------`
IV: 5341476770067C80000 GCM-tag: 5E3EF7A41EF54AD723BACDCA Encrypted text: "C68A25"
The decrypted text is: "HAI"
IV: 5341476770067C80001 GCM-tag: EBB7E542AB58418F29C4E34 Encrypted text: "944D317552"
The decrypted text is: "HAI_1"
IV: 5341476770067C80002 GCM-tag: 96DC7B3CE531DBC3D54CD630 Encrypted text: "D413AAB35"
The decrypted text is: "HAI_2"
IV: 5341476770067C80003 GCM-tag: A6C95C238F66AD7D2152EC5 Encrypted text: "D51B68ACC3"
The decrypted text is: "HAI_3"
How many bytes are needed to send the 5 bytes of plaintext?
If you need to encrypt bigger messages ( more than 200 byte), the classical Arduino boards with about 2000 byte of SRAM will limit your texts. Use ESP boards instead.