1

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()
{
}
  • Hint#1: sizeof(&hashvalue); is not the length of the string. It is the number of bytes of a pointer. – Mikael Patel May 17 '19 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. – Mikael Patel May 17 '19 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. – Mikael Patel May 17 '19 at 19:28
  • Thank you very much for helping – bomberb17 May 18 '19 at 2:57
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!

|improve this answer|||||
  • 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? – bomberb17 May 17 '19 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. – Mikael Patel May 17 '19 at 17:50
  • ok right, just want to solve my problem in its entirety – bomberb17 May 17 '19 at 18:14
  • Updated my code again, it works but it doesn't output the correct hash, outputs "ffe9aaeaa2a2d5048174df0b80599ef0197ec024c4b051bc9860cff58ef7f9f3" instead of "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" – bomberb17 May 17 '19 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]);
    }
}
|improve this answer|||||
  • Nice implementation! Could avoid sprintf() to reduce program memory size. – Mikael Patel May 18 '19 at 12:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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