SHA256 encryption for Dynamodb

Hello,
I want to build station which will upload data to Amazon DanamoDB, so I should encrypt some key and messages using sha256.
So, I should perform a step by step encryption, where output of one encryption is the secret key to the next.
My problem is this, only the first encryption works well with correct output. Next encryptions are faulty.
I compare the output which same outputs from python program, which works well.
Is there anyone who faced the same problem and could help me.
I upload the code, which make the encryption, without network part

#include "sha256.h"
const char signed_head[] PROGMEM = "content-type;host;x-amz-date;x-amz-target"; 
const char bodya[] PROGMEM = "{\"TableName\": \"gaiokthmonas_ektash1\", \"Item\": {\"meastime\": {\"S\": \"202105270852\"}, \"humidity\": {\"N\": \"0.5\"}, \"temperature\": {\"N\": \"22\"}}\0";
const char bodyb[] PROGMEM = ", \"ConditionExpression\": \"attribute_not_exists(meastime)\"}\0";
const char can_head0[] PROGMEM = "content-type:application/x-amz-json-1.0\nhost:dynamodb.eu-west-2.amazonaws.com\nx-amz-date:";
const char can_head1[] PROGMEM = "\nx-amz-target:DynamoDB_20120810.PutItem\n";
const char string_5[] PROGMEM = "String 5";

const char *const string_table[] PROGMEM = {signed_head, bodya, bodyb, can_head0, can_head1, string_5};

aws_secret_access_key[45]="xxxxxxxxxxxxxxx\0";
                                

char utc_time[16] = "20210527T055121Z";
char utc_date[8] = "20210527";

char can_method[4] = "POST";
char can_uri[1] = "/";
char can_query_string[1] = "";
char region[9] = "eu-west-2";
char can_head[290];
char body[221];



void CryptoMessage(uint8_t *result_digest, uint8_t *secret_key,int key_len, char *message, int message_len){
  message[message_len-1]='\0';
  secret_key[key_len-1]='\0';
  message_len=message_len-1;
  key_len=key_len-1;
//  Serial.println("function");
//  Serial.print("message: ");
//  Serial.print(message);
//  Serial.print(" message len: ");
//  Serial.println(message_len);
//  Serial.print("secret_key: ");
//  Serial.print(secret_key);
//  Serial.print(" key_len: ");
//  Serial.println(key_len);
  
  Sha256.initHmac(secret_key, key_len); 
  Sha256.print(message);
  uint8_t * result = Sha256.resultHmac();

  char hexencoded[64];
  strncpy(result_digest,result,64); 
  result_digest[64] = '\0';
  
  
  for(int i = 0; i < 64; i+=2){
    hexencoded[i] = "0123456789abcdef"[result[i / 2] >> 4];
    hexencoded[i + 1] = "0123456789abcdef"[result[i / 2] & 0xf];
    }
//  encoded[64]='\0';
  Serial.print("hexencoded: ");
  Serial.println(hexencoded);
  Serial.println("-------");

}
char buffer[159];
void setup(void)
{
  Serial.begin(9600);
  Serial.println("======");
  strcpy_P(buffer, (char *)pgm_read_word(&(string_table[1])));  
  strcpy(body, buffer);
  strcpy_P(buffer, (char *)pgm_read_word(&(string_table[2])));  
  strcat(body, buffer);
  Serial.println(body);
  Serial.println("======");

  can_head[0]=0;//empty char array
  strcpy_P(buffer, (char *)pgm_read_word(&(string_table[3])));
  strcpy(can_head,buffer );
  strcat(can_head, utc_time);
  strcpy_P(buffer, (char *)pgm_read_word(&(string_table[4])));
  strcat(can_head, buffer);
  Serial.println(can_head);
  Serial.println("======");  
  Serial.println("\"\"");  

  char encodedMessage[65];
  char message[9]="20210527";
  message[8]='\0';
  char messageDate[9] = "20210527";
  messageDate[8]='\0';
  char messageRegion[10] = "eu-west-2";
  messageRegion[9] ='\0';
  char messageServive[9] = "dynamodb";
  messageServive[8] ='\0';
  char messageSigning[13] = "aws4_request";
  messageSigning[12] ='\0';
  Serial.println(message);
  Serial.println(messageDate);
  Serial.println(messageRegion);
  Serial.println(messageServive);
  Serial.println(messageSigning);
  
  uint8_t kDate[65];
  uint8_t kRegion[65];
  uint8_t kService[65];
  uint8_t kSigning[65];
  
  Serial.println("kDate: ");
  CryptoMessage(kDate,aws_secret_access_key,sizeof(aws_secret_access_key),messageDate,sizeof(messageDate)); //ypologismos kDate
  //Serial.println(encodedMessage);
  Serial.println("KRegion: ");
  CryptoMessage(kRegion,kDate,sizeof(kDate),messageRegion,sizeof(messageRegion)); //ypologismos kRegion
  //Serial.println(encodedMessage);
  Serial.println("Kservice: ");
  CryptoMessage(kService,kRegion,sizeof(kRegion),messageServive,sizeof(messageServive)); //ypologismos kService
  //Serial.println(encodedMessage);
  Serial.println("kSigning: ");
  CryptoMessage(kSigning,kService,sizeof(kService),messageSigning,sizeof(messageSigning)); //ypologismos kSigning
  //Serial.println(encodedMessage);
  //Serial.println("kSigning -> ...");
  /*CryptoMessage(encodedMessage,aws_secret_access_key,sizeof(aws_secret_access_key),encodedMessage,sizeof(encodedMessage));
  //CryptoMessage(encodedMessage,aws_secret_access_key,sizeof(aws_secret_access_key),encodedMessage,sizeof(encodedMessage)); // de xreiazetai auto
  Serial.println(encodedMessage);
  */
  

}


void loop(void)
{}

Hello, do yourself a favour and please read How to get the best out of this forum and modify your post accordingly (including code tags and necessary documentation of your ask).

are you overstepping your array bounds?

  strncpy(result_digest,result,64); 
  result_digest[64] = '\0';

Yeap, this is mistake, but unfortunately no the solution. I did it in order to print correctly the encrypted message to Serial port. I think that I fix it and this is the code now

#include "sha256.h"
//#include <avr/pgmspace.h> //gia gia to progrem alla den e;inai aparaitith
const char signed_head[] PROGMEM = "content-type;host;x-amz-date;x-amz-target"; 
const char bodya[] PROGMEM = "{\"TableName\": \"gaiokthmonas_ektash1\", \"Item\": {\"meastime\": {\"S\": \"202105270852\"}, \"humidity\": {\"N\": \"0.5\"}, \"temperature\": {\"N\": \"22\"}}\0";
const char bodyb[] PROGMEM = ", \"ConditionExpression\": \"attribute_not_exists(meastime)\"}\0";
const char can_head0[] PROGMEM = "content-type:application/x-amz-json-1.0\nhost:dynamodb.eu-west-2.amazonaws.com\nx-amz-date:";
const char can_head1[] PROGMEM = "\nx-amz-target:DynamoDB_20120810.PutItem\n";
const char string_5[] PROGMEM = "String 5";

const char *const string_table[] PROGMEM = {signed_head, bodya, bodyb, can_head0, can_head1, string_5};

char aws_secret_access_key[45]="xxxxxxxxxxxx\0";
                                

char utc_time[16] = "20210527T055121Z";
char utc_date[8] = "20210527";

char can_method[4] = "POST";
char can_uri[1] = "/";
char can_query_string[1] = "";
char region[9] = "eu-west-2";
char can_head[290];
char body[221];



void CryptoMessage(uint8_t *result_digest, uint8_t *secret_key,int key_len, char *message, int message_len){
  message[message_len-1]='\0';
  secret_key[key_len-1]='\0';
  message_len=message_len-1;
  key_len=key_len-1;
//  Serial.println("function");
//  Serial.print("message: ");
//  Serial.print(message);
//  Serial.print(" message len: ");
//  Serial.println(message_len);
//  Serial.print("secret_key: ");
//  Serial.print(secret_key);
//  Serial.print(" key_len: ");
//  Serial.println(key_len);
  
  Sha256.initHmac(secret_key, key_len); 
  Sha256.print(message);
  uint8_t * result = Sha256.resultHmac();

  char hexencoded[64];
  strncpy(result_digest,result,64); 

  
  
  for(int i = 0; i < 64; i+=2){
    hexencoded[i] = "0123456789abcdef"[result[i / 2] >> 4];
    hexencoded[i + 1] = "0123456789abcdef"[result[i / 2] & 0xf];
    }

  Serial.print("hexencoded: ");
  Serial.println(hexencoded);
  Serial.println("-------");

}
char buffer[159];
void setup(void)
{
  Serial.begin(9600);
  Serial.println("======");
  strcpy_P(buffer, (char *)pgm_read_word(&(string_table[1])));  
  strcpy(body, buffer);
  strcpy_P(buffer, (char *)pgm_read_word(&(string_table[2])));  
  strcat(body, buffer);
  Serial.println(body);
  Serial.println("======");

  can_head[0]=0;//empty char array
  strcpy_P(buffer, (char *)pgm_read_word(&(string_table[3])));
  strcpy(can_head,buffer );
  strcat(can_head, utc_time);
  strcpy_P(buffer, (char *)pgm_read_word(&(string_table[4])));
  strcat(can_head, buffer);
  Serial.println(can_head);
  Serial.println("======");  
  Serial.println("\"\"");  

  char encodedMessage[64];
  char message[9]="20210527";
  message[8]='\0';
  char messageDate[9] = "20210527";
  messageDate[8]='\0';
  char messageRegion[10] = "eu-west-2";
  messageRegion[9] ='\0';
  char messageServive[9] = "dynamodb";
  messageServive[8] ='\0';
  char messageSigning[13] = "aws4_request";
  messageSigning[12] ='\0';
  Serial.println(message);
  Serial.println(messageDate);
  Serial.println(messageRegion);
  Serial.println(messageServive);
  Serial.println(messageSigning);
  
  uint8_t kDate[64];
  uint8_t kRegion[64];
  uint8_t kService[64];
  uint8_t kSigning[64];
  
  Serial.println("kDate: ");
  CryptoMessage(kDate,aws_secret_access_key,sizeof(aws_secret_access_key),messageDate,sizeof(messageDate)); //ypologismos kDate
  //Serial.println(encodedMessage);
  Serial.println("KRegion: ");
  CryptoMessage(kRegion,kDate,sizeof(kDate),messageRegion,sizeof(messageRegion)); //ypologismos kRegion
  //Serial.println(encodedMessage);
  Serial.println("Kservice: ");
  CryptoMessage(kService,kRegion,sizeof(kRegion),messageServive,sizeof(messageServive)); //ypologismos kService
  //Serial.println(encodedMessage);
  Serial.println("kSigning: ");
  CryptoMessage(kSigning,kService,sizeof(kService),messageSigning,sizeof(messageSigning)); //ypologismos kSigning
  //Serial.println(encodedMessage);
  //Serial.println("kSigning -> ...");
  /*CryptoMessage(encodedMessage,aws_secret_access_key,sizeof(aws_secret_access_key),encodedMessage,sizeof(encodedMessage));
  //CryptoMessage(encodedMessage,aws_secret_access_key,sizeof(aws_secret_access_key),encodedMessage,sizeof(encodedMessage)); // de xreiazetai auto
  Serial.println(encodedMessage);
  */
  

}


void loop(void)
{}

Suggest you replace all your strxxx with strlxxx versions.
strcat is particularly dangerous.
See this example sketch for how to use them and how to detect errors.
strlcpy_strlcat.ino

A few comments:

there is no need to put the null char at the end, it's done for you by C++
char aws_secret_access_key[45] = "xxxxxxxxxxxx\0";

that's not good

char utc_time[16] = "20210527T055121Z";
char utc_date[8] = "20210527";

char can_method[4] = "POST";
char can_uri[1] = "/";
char can_query_string[1] = "";

you don't allow for room for the trailing '\0' the compiler adds. Just do (for example)
char can_method[] = "POST";
and let the compiler figure out the size needed.

I'm reading from my phone so can't see well the whole thing, but this seems to indicate you don't have a good grasp of the buffers and how to deal with length

Which sha256.h library are you using and on what type of Arduino?

This is the library
https://rweather.github.io/arduinolibs/classSHA256.html

You are rightfor the variable can_method and I correct it, but I am not using it at the moment.

Thanks a lot for your time and help

what type of Arduino are you using?

Arduino Mega 2560

I would suggest to keep things simple at first to test your function with known text.

here is an example

#include "SHA256.h"
SHA256 sha256; 

#define HASH_SIZE 32
uint8_t hashResult[HASH_SIZE];

struct t_hashData
{
  const char * cStringPayload;
  const char* key;
  uint8_t hashForCompare[HASH_SIZE];
};

t_hashData const basicHashSample = {
  "this is the data to hash",
  nullptr,
  {
    0x5e, 0xa1, 0xc4, 0x56, 0xff, 0xd1, 0x9e, 0x8e,
    0xed, 0x8d, 0x05, 0x6f, 0x90, 0x86, 0xb3, 0xdc,
    0x7c, 0x08, 0xdb, 0x74, 0xa3, 0x6f, 0x87, 0xf9,
    0x54, 0xc0, 0xaa, 0x2a, 0xe0, 0x2e, 0x10, 0x4b
  }
};


t_hashData const HMACSample = {
  "this is the data to hash",
  "key", // 0x6b 0x65 0x79
  {
    0x72, 0x10, 0x2f, 0x1f, 0x4b, 0x9e, 0xa2, 0x5d,
    0xb1, 0x75, 0xd1, 0x54, 0x88, 0x57, 0xc1, 0xe7,
    0xc3, 0xd7, 0x08, 0x47, 0xc5, 0x87, 0x75, 0x75,
    0x8e, 0x49, 0x9a, 0xce, 0xa4, 0x02, 0xd0, 0xb3
  }
};
void setup() {
  Serial.begin(115200);

  // basic hash
  sha256.reset();
  sha256.update(basicHashSample.cStringPayload, strlen(basicHashSample.cStringPayload));
  sha256.finalize(hashResult, sizeof hashResult);

  if (memcmp(hashResult, basicHashSample.hashForCompare, sizeof hashResult)) {
    Serial.println(F("Error in calculating hash"));
  } else {
    Serial.println(F("SHA256 Hash is fine"));
  }


  // HMAC
  sha256.resetHMAC(HMACSample.key, strlen(HMACSample.key));
  sha256.update(HMACSample.cStringPayload, strlen(HMACSample.cStringPayload));
  sha256.finalizeHMAC(HMACSample.key, strlen(HMACSample.key), hashResult, sizeof hashResult);

  if (memcmp(hashResult, HMACSample.hashForCompare, sizeof hashResult)) {
    Serial.println(F("Error in calculating HMAC hash"));
  } else {
    Serial.println(F("SHA256 HMAC is fine"));
  }
}

void loop() {}

Serial Monitor (@ 115200 bauds) will show

SHA256 Hash is fine
SHA256 HMAC is fine

The hashForCompare values were obtained by using https://cryptii.com

So this seems to work fine. Now it's just a matter for you build the appropriate input cString

Yes you are correct. My misunderstanding of who to use strings was the problem

hope you got it working now !
have fun

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