B4R Tutorial ESP32: AES-256 with IV (CBC, PKCSNoPadding) example via Inline C

KMatle

Expert
Licensed User
Finally I got it working. Maybe the Inline C code is not that elegant :) I was too lazy to add a Salt (which I will update later). Hardest part (for me as I don't like C since the 90ies) was to exchange the data between B4R Main and the Inline C. However: I got it.

Note: As PKCSNoPadding ist used, the string (exactly: Bytes) to be encrypted must be a multiple of 16. Otherwise it will not work with B4x.

The next weekend or so I will provide the counterpart in B4x via WiFi/AsyncStreams and Salt will be added to have it "state of the art".

See my tutorial about AES: https://www.b4x.com/android/forum/threads/b4x-aes-encryption-lessons-learned-best-practice.97927/

Needed lib: rRandomAccessFile (for the ByteConverter)

Code:

B4X:
#Region Project Attributes
    #AutoFlushLogs: True
    #CheckArrayBounds: True
    #StackBufferSize: 5000
    #DefineExtra: #define SKIP_B4RNEW
#End Region

Sub Process_Globals
    Public Serial1 As Serial
  
    Public bc As ByteConverter
  
    Public plaintext(256) As Byte 'Must be a multiple of 16 as PKCSNoPadding is used
    Public iv(16) As Byte 'initialization vector. Must be the same for enc- and decryption
    Public pw(32) As  Byte 'pw/key (will be hashed to 32 bytes)
    Public encrypted(256) As  Byte
  
  
End Sub

Private Sub AppStart
  
    Serial1.Initialize(115200)
  
    Log("*** B4R AppStart ***")
  
    'Set IV (exact 16 bytes)
    For i=0 To 15
        iv(i)=i
    Next
  
    'Set plaintext
    Dim TextToEncrypt As String="Hello world!"
    bc.ArrayCopy2(TextToEncrypt.GetBytes,0,plaintext,0,TextToEncrypt.Length)
  
    'Set pw/key
    Dim pws As String="MySecretKey"
    bc.ArrayCopy(pws.GetBytes,pw)
  
    'Encrypt plaintext
    RunNative("Encrypt", Null)
    Log("Encrypted (as HEX string): ",bc.HexFromBytes(encrypted))
  
    'Decrypt it
    RunNative("Decrypt", Null)
    Log("Decrypted: ",bc.StringFromBytes(plaintext))

End Sub



#if C
#include <mbedtls/aes.h>
#include "mbedtls/md.h"

char encrypted[256];
char plaintext[256];
char ivc[16];

void Encrypt (B4R::Object* o) {

char *texttoencrypt = (char*)b4r_main::_plaintext->data;
memcpy(plaintext, texttoencrypt, strlen(texttoencrypt));
char *pw = (char*)b4r_main::_pw->data;
char *ivc = (char*)b4r_main::_iv->data;


//256Hash the PW (32 Bytes)
  byte shaResult[32];
  mbedtls_md_context_t hash;
  mbedtls_md_type_t md_type = MBEDTLS_MD_SHA256;
  const size_t pwLength = strlen(pw);        
  mbedtls_md_init(&hash);
  mbedtls_md_setup(&hash, mbedtls_md_info_from_type(md_type), 0);
  mbedtls_md_starts(&hash);
  mbedtls_md_update(&hash, (const unsigned char *) pw, pwLength);
  mbedtls_md_finish(&hash, shaResult);
  mbedtls_md_free(&hash);
  uint8_t key[32];
  memcpy(key, shaResult, 32);
 //***********************************************************************************
  
    uint8_t ivu[16];

//Set IV
    int i;
    for( i = 0; i < 16; i++ )
    {
    ivu[i]=ivc[i];
    }

esp_aes_context ctx;
esp_aes_init( &ctx );
esp_aes_setkey( &ctx, key, 256 );
esp_aes_crypt_cbc( &ctx, ESP_AES_ENCRYPT, sizeof(plaintext), ivu, (uint8_t*)plaintext, (uint8_t*)encrypted );

b4r_main::_encrypted->data=encrypted;
memset( plaintext, 0, sizeof( plaintext ) );
b4r_main::_plaintext->data=plaintext;

esp_aes_free( &ctx );


}

void Decrypt (B4R::Object* o) {

char *pw = (char*)b4r_main::_pw->data;
char *ivc = (char*)b4r_main::_iv->data;

//256Hash the PW (32 Bytes)
  byte shaResult[32];
  mbedtls_md_context_t hash;
  mbedtls_md_type_t md_type = MBEDTLS_MD_SHA256;
  const size_t pwLength = strlen(pw);        
  mbedtls_md_init(&hash);
  mbedtls_md_setup(&hash, mbedtls_md_info_from_type(md_type), 0);
  mbedtls_md_starts(&hash);
  mbedtls_md_update(&hash, (const unsigned char *) pw, pwLength);
  mbedtls_md_finish(&hash, shaResult);
  mbedtls_md_free(&hash);
  uint8_t key[32];
  memcpy(key, shaResult, 32);
 //***********************************************************************************
  
    uint8_t ivu[16];

//Set IV

    int i;
    for( i = 0; i < 16; i++ )
    {
    ivu[i]=ivc[i];
    }

esp_aes_context ctx;
esp_aes_init( &ctx );
esp_aes_setkey( &ctx, key, 256 );

char *b4renc = (char*)b4r_main::_encrypted->data;
memcpy(encrypted, b4renc, strlen(b4renc));

memset( plaintext, 0, sizeof( plaintext ) );

esp_aes_crypt_cbc( &ctx, ESP_AES_DECRYPT, sizeof(encrypted), ivu, (uint8_t*)encrypted, (uint8_t*)plaintext );
  
b4r_main::_plaintext->data=plaintext;

esp_aes_free( &ctx );

}
#End if
 
Last edited:
Top