In this tutorial we will check how to generate the hash of a string using the SHA-256 algorithm on the Arduino core running on the ESP32, with the mbed TLS libraries.

SHA-256 is a hashing algorithm of the SHA-2 family [1] and it produces a fixed 256 bits length output independently of the size of the input. You can read more about hashing algorithms here.

The tests were performed using a DFRobot’s ESP32 module integrated in a ESP32 development board.

The code

First we need to include the md.h file from the mbed TLS library. This file exposes a generic interface that wraps the available hashing functions available on the mbed TLS library. You can check the header file here and its documentation here.

If you prefer using the SHA-256 specific functions, you can alternatively use the interface defined in this header file. Note however that the function calls we will see below would need to be different.

#include "mbedtls/md.h"

Moving on to the setup function, we will start by opening a serial connection, to later output the results of the program and then obtain them on the Arduino IDE serial monitor when testing the code. 


Next we need to specify the content to which we will apply the SHA-256 algorithm. I will use the string shown below but you can try with other content.

char *payload = "Hello SHA 256!";

 Additionally, we will need a byte buffer to store the result of the algorithm. Since the output of the algorithm has a length of 256 bits, then our buffer needs to have a length of 32 bytes (a byte corresponds to 8 bits, to 32 bytes correspond to 256 bits).

byte shaResult[32];

We will also need a variable of type mbedtls_md_context_t. This struct will be passed to the functions we will call later and it is used to keep internal state between the mentioned function calls. 

mbedtls_md_context_t ctx;

Next we need to declare a variable of type mbedtls_md_type_t. This type corresponds to an enum representing the different message digest algorithms supported by the mbed TLS libraries and you can check all its values here.

In our case, since we are working with the SHA-256 algorithm, then we need to use the MBEDTLS_MD_SHA256 enumerated value.

mbedtls_md_type_t md_type = MBEDTLS_MD_SHA256;

 Before starting to call the mbed TLS functions, we will declare a variable to hold the length of the payload, since we will need to provide this value to one of the functions we will call later.

const size_t payloadLength = strlen(payload);

Moving on to the function calls, the first thing we need to do is initializing the context we previously declared. To do it, we simply need to call the mbedtls_md_initfunction, passing as input a pointer to the context.


Next we need to call the mbedtls_md_setup function, in order to specify the hash function to be used.

As we did before, we pass as first argument a pointer to the context struct.

As second argument, we need to pass a variable of type mbedtls_md_info_t. As can be seen in this header file, this struct contains some information about the hash algorithm to be used and some pointers to generic functions that will be used under the hood.

Note that we previously declared an enumerated value representing the algorithm we are going to use and now we need to obtain the corresponding mbedtls_md_infostruct. We can do it by calling the mbedtls_md_info_from_type, passing as input the enumerated value we have declared before.

As third argument, the mbedtls_md_setup function receives an integer to specify if we are going to use the HMAC mechanism (we should pass 1) or not (we should pass 0). If HMAC is not used, passing 0 allows to save some memory, as stated in the function documentation. Since we are not going to use HMAC we will pass 0.

Read more »