ESP32 RSA 2048 Encrypt/Decrypt (working code)

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

Do You have a question or is this a kind of
"how to"?

:sweat_smile:
Hello @Railroader

Sorry, I'm new posting here, I'm posting a working code for RSA, no questions, everything its ok.

:v:

There is a section for working probects.
Sorry, bedtiime here, tired. Hopeful,y a more alert helper can fill in the gap.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.