2

In my Arduino project I want to compute the SHA256 hash of a string and store the result to a string, and do this recursively many times (i.e. compute hash of hash of hash etc...). So my goal is to have a reliable function as follows:

String h(String input) {
...
return output;
}

where for example h("abc") would return "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad".

I downloaded this library (from Tools->Manage libraries, it is also in github) and then ran the example in TestSHA256.ino which passes all the checks. However I'm stuggling to make my function work since the library doesn't have a specific example on how to compute and return a SHA256 hash.

I have been looking in function testHash_N() in TestSHA256.ino, which appears to create a hash (from struct TestHashVector data) and compare it with the precomputed hash (from struct TestHashVector hash[]).

The hash seems to be computed in lines 89-96 in TestSHA256.ino. I just want to take the actual hash string result, so for testVectorSHA256_1 in the example, I would need to have a string = "ba7816bf....15ad" as the result.

I understand that this is related to memory referencing in Arduino but I'm not experienced so I'd be grateful if you helped me with this.

EDIT: My code snippet so far is as follows, but it doesn't output the correct hash..

#include <Crypto.h>
#include <SHA256.h>
#include <string.h>

#define HASH_SIZE 32
#define BLOCK_SIZE 64

char hex[256];

char *hashvalue;

SHA256 sha256;

byte buffer[128];


char *btoh(char *dest, uint8_t *src, int len) {
  char *d = dest;
  while( len-- ) sprintf(d, "%02x", (unsigned char)*src++), d += 2;
  return dest;
}

char* h(Hash *hash, char* hashvalue)
{
    size_t size = sizeof(&hashvalue);
    size_t posn, len;
    size_t inc = sizeof(&hashvalue);
    uint8_t value[HASH_SIZE];

    hash->reset();
    for (posn = 0; posn < size; posn += inc) {
        len = size - posn;
        if (len > inc)
            len = inc;
        hash->update(&hashvalue + posn, len);
    }
    hash->finalize(value, sizeof(value));

    return(btoh(hex, value, 32));
}


void setup()
{
    Serial.begin(115200);

    bool tmp;
    char *testvalue = "abc";
    Serial.println(h(&sha256,*testvalue));


}

void loop()
{
}
4
  • Hint#1: sizeof(&hashvalue); is not the length of the string. It is the number of bytes of a pointer. May 17, 2019 at 19:25
  • Hint#2: *testvaluein the statement h(&sha256,*testvalue)); is not a pointer. It is actually the value of the first character, a in the testvalue. May 17, 2019 at 19:27
  • Hint#3: uint8_t value[HASH_SIZE]; is a local value and cannot be returned. static uint8_t value[HASH_SIZE]; will allow that. May 17, 2019 at 19:28
  • Thank you very much for helping
    – Panos
    May 18, 2019 at 2:57

2 Answers 2

0

The main trick is to understand how the Arduino String class works. You can find the source code in your installation of the Arduino IDE or on github.

The basic pattern you are looking for is:

String h(String& input) {      // Pass String by reference to avoid copying
  char output[OUTPUT_MAX];
  char* data = input.c_str();  // Access to internal buffer
  ...
  return String(output);       // Return a String object of the output
}

Cheers!

4
  • Thanks, I've updated my question with an attempt to solve this but I'm still struggling with errors, can you please help me with the code inside to make it work?
    – Panos
    May 17, 2019 at 15:27
  • Yes you have several issues but before going forward please acknowledge that you received an answer to your original question :) and I will get back to you. May 17, 2019 at 17:50
  • ok right, just want to solve my problem in its entirety
    – Panos
    May 17, 2019 at 18:14
  • Updated my code again, it works but it doesn't output the correct hash, outputs "ffe9aaeaa2a2d5048174df0b80599ef0197ec024c4b051bc9860cff58ef7f9f3" instead of "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
    – Panos
    May 17, 2019 at 18:24
0

I suggest the following function. That replaces a string by its hash. It's done in place in order to save memory. Make sure the buffer you give it is at least 65 bytes long. Warning: not tested.

#include <Crypto.h>
#include <SHA256.h>

#define HASH_SIZE 32

SHA256 sha256;

/*
 * Replace a string by its hash, in place.
 * `data' should point to a buffer at least 65 bytes in length.
 */
hash_in_place(char *data)
{
    uint8_t value[HASH_SIZE];

    sha256.reset();
    sha256.update(data, strlen(data));
    sha256.finalize(value, sizeof(value));

    // Convert to hex into the original buffer.
    data[0] = '\0';
    for (size_t i = 0; i < HASH_SIZE; i++) {
        data += sprintf("%02x", value[i]);
    }
}
1
  • Nice implementation! Could avoid sprintf() to reduce program memory size. May 18, 2019 at 12:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.