This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Example of using ESP32 Arudino mbed library to | |
// Encrypt and Decrypt using an asyncronous RSA 2048 bit public and private key pair | |
// created 2020-07-05 by Noah Coad | |
// | |
// Inside a "data" directory, run these commands to generate a key pair | |
// then use the ESP32 Sketch Data Uploader to upload files to ESP32 SPIFFS files | |
// | |
// openssl genrsa -out private-rsa 2048 | |
// openssl pkcs8 -topk8 -inform pem -in private-rsa -outform pem -nocrypt -out private | |
// openssl rsa -in private -pubout > public | |
// | |
// Thanks to these resources for getting me started: | |
// https://www.b4x.com/android/forum/threads/using-rsa-on-a-esp32-via-inline-c.104325/ | |
// | |
#include "SPIFFS.h" | |
#include "mbedtls/pk.h" | |
#include "mbedtls/ctr_drbg.h" | |
#include "mbedtls/entropy.h" | |
#include "mbedtls/error.h" | |
#include "mbedtls/platform.h" | |
#include "libb64/cdecode.h" | |
#include "libb64/cencode.h" | |
void listDir(fs::FS &fs, const char * dirname, uint8_t levels = 0); | |
void setup() { | |
Serial.begin(115200); | |
// this is essential for mbed to be able to read files | |
SPIFFS.begin(); | |
// show files to confirm keys are present | |
listDir(SPIFFS, "/"); | |
readFirstLine("/spiffs/public"); | |
// perform the encrpyion/decryption | |
RSA(); | |
} | |
// list files in SPIFFS | |
void readFirstLine(const char* path) { | |
FILE* f = fopen(path, "r"); | |
if (f == NULL) { | |
Serial.println("Failed to open file for reading"); | |
return; | |
} | |
char line[64]; | |
fgets(line, sizeof(line), f); | |
fclose(f); | |
Serial.println(line); | |
} | |
// list files in SPIFFS | |
void listDir(fs::FS &fs, const char * dirname, uint8_t levels) { | |
Serial.printf("Listing directory: %s\r\n", dirname); | |
File root = fs.open(dirname); | |
if (!root) { | |
Serial.println("- failed to open directory"); | |
return; | |
} | |
if (!root.isDirectory()) { | |
Serial.println(" - not a directory"); | |
return; | |
} | |
File file = root.openNextFile(); | |
while (file) { | |
if (file.isDirectory()) { | |
Serial.print(" DIR : "); | |
Serial.println(file.name()); | |
if (levels) { | |
listDir(fs, file.name(), levels - 1); | |
} | |
} else { | |
Serial.print(" FILE: "); | |
Serial.print(file.name()); | |
Serial.print("\tSIZE: "); | |
Serial.println(file.size()); | |
} | |
file = root.openNextFile(); | |
} | |
} | |
// perform RSA encryption | |
void RSA() { | |
unsigned char encrypted[MBEDTLS_MPI_MAX_SIZE]; | |
unsigned char decrypted[MBEDTLS_MPI_MAX_SIZE]; | |
memset(encrypted, 0, sizeof(encrypted)); | |
memset(decrypted, 0, sizeof(decrypted)); | |
// initilize context | |
int ret = 0; | |
mbedtls_pk_context pk; | |
mbedtls_pk_init( &pk ); | |
// read the public key | |
if ((ret = mbedtls_pk_parse_public_keyfile(&pk, "/spiffs/public")) != 0) | |
{ | |
printf("Public key read failed\nmbedtls_pk_parse_public_keyfile returned -0x%04x\n", -ret); | |
char errbuf[256]; | |
mbedtls_strerror(ret, errbuf, 200); | |
mbedtls_printf("Last error was: -0x%04x - %s\n\n", (int) - ret, errbuf); | |
} | |
else printf("Public Key loaded.\n"); | |
// prep opperating context | |
size_t olen = 0; | |
unsigned char to_encrypt[] = "This is a test..."; | |
// unsigned char to_encrypt[] = "{\"num\":\"1234123412341234\",\"exp\":\"12/23\",\"zip\":\"75002\"}"; | |
size_t to_encrypt_len = sizeof(to_encrypt); | |
mbedtls_ctr_drbg_context ctr_drbg; | |
char *personalization = "my_app_specific_string"; | |
mbedtls_entropy_context entropy; | |
mbedtls_entropy_init(&entropy); | |
mbedtls_ctr_drbg_init(&ctr_drbg); | |
// seed deterministic random byte generator | |
ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, | |
(const unsigned char *) personalization, strlen(personalization)); | |
// perform encryption | |
if ((ret = mbedtls_pk_encrypt(&pk, to_encrypt, to_encrypt_len, | |
encrypted, &olen, sizeof(encrypted), | |
mbedtls_ctr_drbg_random, &ctr_drbg)) != 0) { | |
printf("Encryption failed\nmbedtls_pk_encrypt returned -0x%04x\n", -ret ); | |
char errbuf[256]; | |
mbedtls_strerror(ret, errbuf, 200); | |
mbedtls_printf("Last error was: -0x%04x - %s\n\n", (int) - ret, errbuf); | |
} | |
else { | |
printf("\n . Encrypted\n"); | |
printf("Output Length: %i \n", olen); | |
} | |
char encstr[base64_encode_expected_len(olen)]; | |
int enclen = base64_encode_chars(reinterpret_cast<const char*>(encrypted), olen, encstr); | |
printf("base64: %s\n", encstr); | |
// border between encrypting and decrypting | |
// decrypt from base64 encoding | |
// commend these next few lines out to | |
// decode from original encoding instead | |
memset(encrypted, 0, sizeof(encrypted)); | |
char rsabytes[base64_decode_expected_len(strlen(encstr))]; | |
int rsalen = base64_decode_chars(encstr, strlen(encstr), rsabytes); | |
memcpy(encrypted, rsabytes, rsalen); | |
// init for decryption | |
mbedtls_pk_init(&pk); | |
// read private key | |
if ((ret = mbedtls_pk_parse_keyfile(&pk, "/spiffs/private", "")) != 0) { | |
printf("Private key load failed\nmbedtls_pk_parse_keyfile returned -0x%04x\n", -ret ); | |
} | |
else printf("Private Key loaded.\n"); | |
printf("\n . Decryption\n"); | |
printf("Output length: %i \n", olen); | |
// decypt | |
if ((ret = mbedtls_pk_decrypt(&pk, encrypted, olen, decrypted, &olen, | |
sizeof(decrypted), mbedtls_ctr_drbg_random, &ctr_drbg)) != 0) { | |
printf("Decrypted failed\nmbedtls_pk_decrypt returned -0x%04x\n", -ret ); | |
} | |
else { | |
printf("Decrypted Text: %s \n", decrypted); | |
// printBlock(decrypted, 128); | |
} | |
} | |
// print buffer block | |
void printBlock(unsigned char * block, size_t len) { | |
for (int i = 0; i < len; i++ ) { | |
printf( "%02x[%c]%c", block[i], (block[i] > 31) ? block[i] : ' ', ((i & 0xf) != 0xf) ? ' ' : '\n' ); | |
} | |
printf("\n"); | |
} | |
void loop() { | |
// don't need to loop anything here | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment