freematics-traccar-encrypted/esp32/telelogger/telecrypt.cpp

120 lines
3.4 KiB
C++
Raw Normal View History

2024-06-27 22:35:58 -06:00
#include "config.h"
#include <string.h>
#include <stdio.h>
#include <ChaChaPoly.h>
#include <HardwareSerial.h>
void print_hex(const unsigned char *data, size_t length) {
for (size_t i = 0; i < length; ++i) {
Serial.printf("%02x", data[i]);
}
Serial.println();
}
void encrypt_string(const unsigned char *input, size_t length, unsigned char *output) {
// Create an instance of the ChaChaPoly class
ChaChaPoly chachaPoly;
// Initialize the encryption key
unsigned char key[32];
for (int i = 0; i < 32; ++i) {
sscanf(CHACHA20_KEY + 2*i, "%02x", &key[i]);
}
// Set the encryption key
chachaPoly.setKey(key, sizeof(key));
// Generate a random nonce (IV)
unsigned char nonce[12];
esp_fill_random(nonce, sizeof(nonce)); // Use the ESP-IDF random number generator
chachaPoly.setIV(nonce, sizeof(nonce));
// Encrypt the input data
chachaPoly.encrypt(output + sizeof(nonce), input, length);
// Compute the authentication tag
chachaPoly.computeTag(output + sizeof(nonce) + length, chachaPoly.tagSize());
// Prepend the nonce to the output
memcpy(output, nonce, sizeof(nonce));
// Clear the encryption context
chachaPoly.clear();
}
void decrypt_string(const unsigned char *input, size_t length, unsigned char *output) {
// Create an instance of the ChaChaPoly class
ChaChaPoly chachaPoly;
// Initialize the decryption key
unsigned char key[32];
for (int i = 0; i < 32; ++i) {
sscanf(CHACHA20_KEY + 2*i, "%02x", &key[i]);
}
Serial.println("loaded key");
// Set the decryption key
chachaPoly.setKey(key, sizeof(key));
Serial.println("set key");
// Extract the nonce (IV) from the input
unsigned char nonce[12];
memcpy(nonce, input, sizeof(nonce));
chachaPoly.setIV(nonce, sizeof(nonce));
// Check that length is long enough to contain a nonce and a tag.
if (length < sizeof(nonce) + chachaPoly.tagSize()) {
Serial.print("[CHACHA] Input too short to contain nonce and tag: ");
print_hex(input, length);
output[0] = '\0'; // Set output to an empty string
return;
}
Serial.println("did nonce");
// Decrypt the input data
size_t decryptedLength = length - sizeof(nonce) - chachaPoly.tagSize();
chachaPoly.decrypt(output, input + sizeof(nonce), decryptedLength);
Serial.println("did decryption");
// Print the decrypted data as hex values
String decryptedString = "";
for (size_t i = 0; i < decryptedLength; i++) {
decryptedString += (char)output[i];
}
Serial.println(decryptedString);
// Verify the authentication tag
const unsigned char *tagPtr = input + sizeof(nonce) + decryptedLength;
Serial.print("Tag: ");
for (size_t i = 0; i < chachaPoly.tagSize(); i++) {
Serial.print(tagPtr[i], HEX);
Serial.print(" ");
}
Serial.println();
Serial.print("Computed Tag: ");
uint8_t computedTag[16];
chachaPoly.computeTag(computedTag, sizeof(computedTag));
for (size_t i = 0; i < sizeof(computedTag); i++) {
Serial.print(computedTag[i], HEX);
Serial.print(" ");
}
Serial.println();
if (!chachaPoly.checkTag(tagPtr, chachaPoly.tagSize())) {
Serial.println("Authentication failed!");
output[0] = '\0'; // Set output to an empty string
return;
}
///
// Clear the decryption context
chachaPoly.clear();
}