1

So I have been playing around with SHA hashing, but I have run up against a bit of a wall. For some reason, shasum from the command line and SHA1() from openssl in my program produce two difference results.

Code:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <openssl/sha.h>

int main(int argc, char* argv[]){
  int i;
  char data[] = "README";
  size_t length = sizeof(data);
  unsigned char hash[50];

  SHA1(data, length, hash);

  printf("shasum of \"README\" is \n");
  for(i = 0; i<SHA_DIGEST_LENGTH; i++){
    printf("%x", hash[i]);
  }
  printf("\n");

  /*Using shasum utility*/

  int rc = fork();
  if(rc < 0){
    fprintf(stderr, "Fork failed. \n");
    exit(1);
  }
  else if(rc == 0){
    char* myargs[3];
    myargs[0] = strdup("shasum");
    myargs[1] = strdup("README");
    myargs[2] = NULL;
    execvp(myargs[0], myargs);
  }
  wait(NULL);

  return 0;
}

Output:

shasum of "README" is
aabc5996b4a0256158cbaa6eb4e01b3aa992d942
827cc372e1a3c99b66f6ad820b223939c68bd389  README

The first hash is from SHA1 and the second hash is from shasum (fork/exec from within program). What is causing this?

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
okayJay
  • 11
  • 1
  • 2
  • 1
    Doesn't shashum calculate the digest for the *file* called README (as opposed to the string README)? – Thilo Oct 29 '14 at 03:19
  • 1
    Your `length` variable doesn't hold the value you think it does. Try `strlen` instead of `sizeof`. – Rob Kennedy Oct 29 '14 at 03:19
  • FWIW: `$ echo -n README | openssl sha1` yields `69e27356ef629022720d868ab0c0e3394775b6c1` – Thilo Oct 29 '14 at 03:19
  • As Rob said, your length is wrong since `sizeof` includes the null character. And as Thilo said, `shasum` is reading from a file called `README`, not a string. So you're comparing apples and oranges here. Best delete the question as it has no value to others. – ooga Oct 29 '14 at 03:23

1 Answers1

3

The problem is that the command-line function "shasum" takes as an argument a filename, whereas the openssl-library C-function "shasum" takes as an argument the actual data.

That is, you are comparing the result of the hash of the file named README to the result of the hash of the string "README".

To see both of calculations result the same, just change:

SHA1(data, length, hash);

to

SHA1(data, length-1, hash);

As Jonathan Leffler said, this is to correct the fact that you're including the terminating '\0'.

For the other calculation, you could do echo -n README | shasum to see the real hash. Or, to see it result ok in your program, just output it to a file named README: echo -n README > README.

Your program will then output:

shasum of "README" is 
69e27356ef629022720d868ab0c0e3394775b6c1
69e27356ef629022720d868ab0c0e3394775b6c1  README

EDIT:

If you want to use the SHA1 function to calculate the hash of the readme file, you would have to read the file (see You would need to programatically read the file to a char* buffer, ( see Reading the whole text file into a char array in C) and pass this buffer to the SHA1 function.

Community
  • 1
  • 1
Márcio Paiva
  • 983
  • 9
  • 25
  • 2
    And, additionally, the string being hashed has a null byte included in it. – Jonathan Leffler Oct 29 '14 at 03:44
  • Everyone's feedback was all very informative. I see the main error of my ways, namely confusing the string hash with the file hash. With your correction, you demonstrated how to find the hash both ways for the string case; for the other case, what data do I have to provide SHA1 in the program to get the hash of the file README? – okayJay Oct 29 '14 at 06:47
  • See the edit. You would need to read the file into an array yourself, and then pass this array to the SHA1 function. – Márcio Paiva Oct 29 '14 at 14:48