Sample code to do an RSA ENC/DEC on ESP32, using key pair on flash as a variable.
Note: to do it with a file, you must change the function to load the respective key from a file from SPIFFS, passing the file path.
The main file:
/** Source:
*
* https://mbed-tls.readthedocs.io/en/latest/kb/how-to/encrypt-and-decrypt-with-rsa/#/rsa-source-code
*
*/
#include "mbedtls/pk.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/entropy.h"
#include "rsa_keys.h"
#define TIMER_START true
#define TIMER_STOP false
#define MAX_SIZE_TO_ENCRYPT 245
// unsigned char to_encrypt[] = "Deoxyribonucleic acid (DNA) is a polymer composed of two polynucleotide chains that coil around each other to form a double helix.";
unsigned char to_encrypt[] = "Deoxyribonucleic acid (DNA) is a polymer composed of two polynucleotide chains that coil around each other to form a double helix. The polymer carries genetic instructions for the development, functioning, growth and reproduction of all known organisms and many viruses.";
unsigned char encrypted[MBEDTLS_MPI_MAX_SIZE];
unsigned char decrypted[MBEDTLS_MPI_MAX_SIZE];
void setup()
{
Serial.begin(115200);
delay(1700); // Enough time to open the serial port.
Check_time(TIMER_START);
rsa_pub_init();
rsa_pub_encrypt();
Check_time(TIMER_STOP);
Check_time(TIMER_START);
rsa_priv_init();
rsa_priv_dec();
Check_time(TIMER_STOP);
}
void loop()
{
}
void Check_time(bool mode)
{
static uint32_t start;
uint32_t stop;
if (mode == TIMER_START)
{
start = millis();
}
else
{
stop = millis();
Serial.printf("\r\nProcessing time: %d ms\r\n", stop-start);
}
}
// End of file.
The rsa_keys.h file:
#pragma once
//
// 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/
//
/** Note: This rsa keys were made as example and do not must be used on your final code.
*
* Sources:
*
* (mbedtls code guidelines).
* https://mbed-tls.readthedocs.io/en/latest/kb/how-to/encrypt-and-decrypt-with-rsa/#/rsa-source-code
*
* (Random and Entropy).
* https://mbed-tls.readthedocs.io/en/latest/kb/how-to/add-a-random-generator/
*
* (Full working code using File System, SPIFFS).
* https://gist.github.com/noahcoad/00ac0e8fdff0be0d927bfa8f35879644
*
* Tools (Online RSA key pais generator).
* https://cryptotools.net/rsagen
*/
const unsigned char private_key[] PROGMEM = R"=====(
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC4bbeo61cybob9
4fXUXsEp49e+Whg9O9pRhEpnezOka5oX4ti83IITb6E4AAad5rP+wtCjnuSI5RaR
ZhlntjcDAbeT8TmtivJonJPxZknvt5La6POOy4sXISaEyZPA3WYfA6gxaOYHsf8S
lAMHdr2Nk+L1mkFlyTw3FlY+0npwrBLk8BfpG3hWjbqMfVAMDy3NOiDckNHzole5
PEUhUk8Fo6fDHpWtbgMZVucpbnWBiPhvOeHMkO0Eh/ZgrREbgQo+b1ytrRQP5ivt
fd6bMt9ceo8Sfqq/SMmBbBht7wkR1+XSqDuYdtmxAQUgmswpvqOh1zfZ0CPR3JW+
44JWe1I5AgMBAAECggEACP8SIc9sExnU5CrK8/N00vsqJZ8NtmP2afpM6lgWTG+S
xlZCmhDcGABeogWPTRHJRzS/2nFoZrydEZXkSJy4+YCykKkIVhy0ZzG3HkQN+H9x
DpRlOBqZ8/SCJWFTX6m1Hu9t244pRWgTgBef/7PVOoQjorUl+kX7FdlVNu6LujX3
Zg9NTOXb5GCjMYt8cYLAUADYB1K4FMftrhWUeiJJFefD1ALez6M/cIbE9et6YFPy
i9ciuVf86Nx53jx2zVl5Ca0DYhB0SSCflH/s30aYHub4x/BdB+6NLJ0atynaW5ug
88yvi979RwWa0cynnyhIEu4WLwBdHV3kijRk5OA74QKBgQDhSWspyO7kudEieM2T
nh2REtpDgkw1u/RcndEbbzz1Y+rn0giwnKrec/XaoLxwqjKyM7FHJZM8Jl+dvth8
D+yuqcxKKCxFDE94hal0agzDTHYrrHzOmT4RZEEId+ao8M7GWBuJAioSlGqjZdwU
gQStlPOqD2rmL9hLp/nsndkX2QKBgQDRklWQqx34GfoEssmXnR/STMuB2ZKQYs0L
WhlZGtWuLdSZKWomup0KLaAckIIHQlDJ/4pcVUYzkUgb4Db5qI0Cc6F0wFBIhCGo
733mjB7SHuJe0jYdB0FVg7IwHvy7gFwb83TljWX7Au6KYHgI4ikFZf44h8GxFlHa
RcNzIDbxYQKBgDSLABBlybnU0L7+d8vnA7RTNk6qdAXQSWTUdfG1Fv2QiTf6F4bB
c2SgnQWZmXmZaGuBfOZAED/mH0TWPv1oZWYzOe9NwU11Wo+cdPIuzb069xCmkRFK
UlySCkzkUgqy5zcBU6K3u4JL1Tc4yYSKtsGZTN8r6122aPb0PWj/Q6O5AoGBAIiV
//BWpiSiAYH4aEzJGgk9BdGuVMiHrC1+3lBlneh0dEASbt2o+Fq+28BiKmzCuta8
FpgQ97z6Le4FFq9mO+jiJdNq16g7fZiV5g9ROXEmsdCs3pnStbEfMQ4N1Bf8E4wg
AwrtOg77nS5Qq0rW43diPurnB8T70AMbPsQUtdphAoGALE31dxq8XvnU5ceaNJvT
NGqS51ROkD2GVnxW+V7VW0HjMDzOe3olRlED4FreHARGPAn+IUuVpxZsIfUNBuOS
DGsuMV6t3CumqVfVNn7Lzil90ZLQwT7n+kofkvnRt/ksJrd/cit1ABrV8kWjvaHr
DwoEUj6eG7ppfFLa1fECkoA=
-----END PRIVATE KEY-----
)=====";
const unsigned char public_key[] PROGMEM = R"=====(
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuG23qOtXMm6G/eH11F7B
KePXvloYPTvaUYRKZ3szpGuaF+LYvNyCE2+hOAAGneaz/sLQo57kiOUWkWYZZ7Y3
AwG3k/E5rYryaJyT8WZJ77eS2ujzjsuLFyEmhMmTwN1mHwOoMWjmB7H/EpQDB3a9
jZPi9ZpBZck8NxZWPtJ6cKwS5PAX6Rt4Vo26jH1QDA8tzTog3JDR86JXuTxFIVJP
BaOnwx6VrW4DGVbnKW51gYj4bznhzJDtBIf2YK0RG4EKPm9cra0UD+Yr7X3emzLf
XHqPEn6qv0jJgWwYbe8JEdfl0qg7mHbZsQEFIJrMKb6jodc32dAj0dyVvuOCVntS
OQIDAQAB
-----END PUBLIC KEY-----
)=====";
// End of file.
The rsa_routines.ino file:
mbedtls_pk_context pk_pub;
mbedtls_pk_context pk_priv;
size_t olen_enc = 0;
size_t olen_dec = 0;
void rsa_pub_init(void)
{
int ret = 0;
mbedtls_pk_init( &pk_pub );
/*
* Read the RSA public key
*/
// if( ( ret = mbedtls_pk_parse_public_keyfile( &pk_pub, public_key ) ) != 0 )
if( ( ret = mbedtls_pk_parse_public_key( &pk_pub, public_key, sizeof(public_key) ) ) != 0 )
{
Serial.printf( " failed\n ! mbedtls_pk_parse_public_keyfile returned -0x%04x\n", -ret );
}
else
{
Serial.printf("\r\nInit success !\r\n");
}
}
void rsa_pub_encrypt(void)
{
int ret = 0;
int to_encrypt_len;// sizeof(to_encrypt);
int temp_size = sizeof(to_encrypt);
to_encrypt_len = (temp_size > MAX_SIZE_TO_ENCRYPT) ? MAX_SIZE_TO_ENCRYPT : temp_size; // If the input string is greater than MAX_SIZE, will be truncated.
char personalization_1[] = "PUT0 31 QU3 10 13A 666"; // Any string.
mbedtls_ctr_drbg_context ctr_drbg;
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_1, strlen(personalization_1));
/*
* Calculate the RSA encryption of the data.
*/
printf( "\n . Generating the encrypted value" );
fflush( stdout );
ret = mbedtls_pk_encrypt( &pk_pub, to_encrypt, to_encrypt_len, encrypted, &olen_enc, sizeof(encrypted), mbedtls_ctr_drbg_random, &ctr_drbg );
if( ret != 0 )
{
printf( " failed\n ! mbedtls_pk_encrypt returned -0x%04x\n", -ret );
// goto exit;
}
else
{
Serial.printf("\r\nEncrypt success !\r\n");
}
}
void rsa_priv_init(void)
{
int ret = 0;
mbedtls_pk_init( &pk_priv );
/*
* Read the RSA privatekey
*/
// if( ( ret = mbedtls_pk_parse_keyfile( &pk_priv, private_key, "" ) ) != 0 )
if( ( ret = mbedtls_pk_parse_key( &pk_priv, private_key, sizeof(private_key), NULL, 0 ) ) != 0 )
{
Serial.printf( " failed\n ! mbedtls_pk_parse_keyfile returned -0x%04x\n", -ret );
}
else
{
Serial.printf("\r\nInit priv_key success !\r\n");
}
}
void rsa_priv_dec(void)
{
int ret = 0;
int to_decrypt_len = olen_enc;
char personalization_2[] = "PUT0 31 QU3 10 13A 999"; // Any string.
mbedtls_ctr_drbg_context ctr_drbg;
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_2, strlen(personalization_2));
/*
* Calculate the RSA encryption of the data.
*/
printf( "\n . Generating the decrypted value" );
fflush( stdout );
if( ( ret = mbedtls_pk_decrypt( &pk_priv, encrypted, to_decrypt_len, decrypted, &olen_dec, sizeof(decrypted), mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
{
Serial.printf( " failed\n ! mbedtls_pk_decrypt returned -0x%04x\n", -ret );
}
else
{
Serial.printf("\r\nDecrypted Text: %s \n", decrypted);
}
}
// End of file.
The output on the serial console:
Init success !
. Generating the encrypted value
Encrypt success !
Processing time: 23
Init priv_key success !
. Generating the decrypted value
Decrypted Text: Deoxyribonucleic acid (DNA) is a polymer composed of two polynucleotide chains that coil around each other to form a double helix. The polymer carries genetic instructions for the development, functioning, growth and reproduction of all known or
Processing time: 529
As you can see, takes 23 milliseconds to encript a char array of 245 bytes (MAX SIZE for RSA 2048), and 529 milliseconds to decrypt it. More secure more processing power.
Sources:
https://mbed-tls.readthedocs.io/en/latest/kb/how-to/encrypt-and-decrypt-with-rsa/#/rsa-source-code
Online RSA key pair generator tool (choose key length 2048):
https://cryptotools.net/rsagen
Also you can use openssl to generate the rsa keys.
Regards