// hasing and encryption library's
#include "mbedtls/md.h"     // HMAC hashing used for the pairing process
#include "mbedtls/base64.h" // Base64 encoding/decoding for the paring proces


// encryption and hashing
mbedtls_md_context_t ctx;
mbedtls_md_type_t md_type = MBEDTLS_MD_SHA256;


const char *pin = "6577";
const char *timestamp = "1156";

#define SECRET_KEY "1111111"

void init_Hash(const char *key)
{
  // calculate size of the key
  const size_t keyLength = strlen(key);

  // init hash function
  mbedtls_md_init(&ctx);
  mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 1);        // setup with the prespecified hash (md_type)
  mbedtls_md_hmac_starts(&ctx, (const unsigned char *) key, keyLength); // start the hash with the Secret key
}


void Update_Hash(const char *data)
{
  // calculate size of the key
  const size_t dataLength = strlen(data);

  // update hash
  mbedtls_md_hmac_update(&ctx, (const unsigned char *) data, dataLength);
}

void Finalize_Hash()
{
  /*
     base64:
     https://pcbartists.com/firmware/base64-encoding-and-decoding-on-esp32/#:~:text=The%20ESP%2DIDF%20contains%20functions,mbedTLS%20base64%20encoding%20and%20decoding.
     https://siliconlabs.github.io/Gecko_SDK_Doc/mbedtls/html/base64_8h.html

     hashing:
     https://tls.mbed.org/api/md_8h.html#adf77ab9b0f117367883988ee5f0af1f4
     https://techtutorialsx.com/2018/01/25/esp32-arduino-applying-the-hmac-sha-256-mechanism/

     calculators
     https://www.freeformatter.com/hmac-generator.html#ad-output
     https://www.base64encode.org/

     HMAC from 11566577 result:
     81d4d97d850c29795ed5e8d6435b3347e982c2fdfc3b5d1b2fc976a3490cc1e4

     Encode with Base64 result:
     ODFkNGQ5N2Q4NTBjMjk3OTVlZDVlOGQ2NDM1YjMzNDdlOTgyYzJmZGZjM2I1ZDFiMmZjOTc2YTM0OTBjYzFlNA==

  */

  byte output_HMAC[32];		// byte datatype is needed to read the output_hmac correct 
  unsigned char output[65];
  size_t outlen;
  
  // return the final HMAC number
  mbedtls_md_hmac_finish(&ctx, output_HMAC);
  mbedtls_md_free(&ctx);
  
  mbedtls_base64_encode(output, 64, &outlen, (unsigned char *)output_HMAC, sizeof(output_HMAC));
  
  // null-terminate the output string
  output[outlen] = 0;
  Serial.println((const char*)output);
  
}

void setup()
{
  // intialize the serialport
  Serial.begin(115200);

  // initialize hash hmac
  init_Hash(SECRET_KEY);

}


void loop()
{
  Serial.println("hashing data");
  Update_Hash(timestamp);
  Update_Hash(pin);
  Finalize_Hash();
	
  //slow down
  delay(10000);
}