How to use SHA1 hashing in C programming

78,385

Solution 1

If you have all of your data at once, just use the SHA1 function:

// The data to be hashed
char data[] = "Hello, world!";
size_t length = strlen(data);

unsigned char hash[SHA_DIGEST_LENGTH];
SHA1(data, length, hash);
// hash now contains the 20-byte SHA-1 hash

If, on the other hand, you only get your data one piece at a time and you want to compute the hash as you receive that data, then use the other functions:

// Error checking omitted for expository purposes

// Object to hold the current state of the hash
SHA_CTX ctx;
SHA1_Init(&ctx);

// Hash each piece of data as it comes in:
SHA1_Update(&ctx, "Hello, ", 7);
...
SHA1_Update(&ctx, "world!", 6);
// etc.
...
// When you're done with the data, finalize it:
unsigned char hash[SHA_DIGEST_LENGTH];
SHA1_Final(hash, &ctx);

Solution 2

The first function (SHA1()) is the higher-level one, it's probably the one you want. The doc is pretty clear on the usage - d is input, n is its size and md is where the result is placed (you alloc it).

As for the other 3 functions - these are lower level and I'm pretty sure they are internally used by the first one. They are better suited for larger inputs that need to be processed in a block-by-block manner.

Solution 3

I believe I should be using either unsigned char *SHA1 or SHA1_Init ...

For later versions of the OpenSSL library, like 1.0.2 and 1.1.0, the project recommends using the EVP interface. An example of using EVP Message Digests with SHA256 is available on the OpenSSL wiki:

#define handleErrors abort

EVP_MD_CTX *ctx;

if((ctx = EVP_MD_CTX_create()) == NULL)
    handleErrors();

if(1 != EVP_DigestInit_ex(ctx, EVP_sha256(), NULL))
    handleErrors();

unsigned char message[] = "abcd .... wxyz";
unsinged int message_len = sizeof(message);

if(1 != EVP_DigestUpdate(ctx, message, message_len))
    handleErrors();

unsigned char digest[EVP_MAX_MD_SIZE];
unsigned int digest_len = sizeof(digest);

if(1 != EVP_DigestFinal_ex(ctx, digest, &digest_len))
    handleErrors();

EVP_MD_CTX_destroy(ctx);

Solution 4

Adam Rosenfield's answer is fine, but use strlen rather than sizeof, otherwise hash will be calculated including null terminator. Which is probably fine in this case, but not if you need to compare your hash with one generated by other tool.

// The data to be hashed
char data[] = "Hello, world!";
size_t length = strlen(data);

unsigned char hash[SHA_DIGEST_LENGTH];
SHA1(data, length, hash);
// hash now contains the 20-byte SHA-1 hash

Solution 5

Calculate hash like this

// Object to hold the current state of the hash
SHA_CTX ctx;
SHA1_Init(&ctx);

// Hash each piece of data as it comes in:
SHA1_Update(&ctx, "Hello, ", 7);
...
SHA1_Update(&ctx, "world!", 6);
// etc.
...
// When you're done with the data, finalize it:
unsigned char tmphash[SHA_DIGEST_LENGTH];
SHA1_Final(tmphash, &ctx);

Finally you can decode hash to human-readable form by code like this.

unsigned char hash[SHA_DIGEST_LENGTH*2];

int i = 0;
for (i=0; i < SHA_DIGEST_LENGTH; i++) {
    sprintf((char*)&(hash[i*2]), "%02x", tmphash[i]);
}
// And print to stdout
printf("Hash: %s\n", hash);
Share:
78,385
spassen
Author by

spassen

Updated on January 20, 2021

Comments

  • spassen
    spassen over 3 years

    I am trying to write a C program that proves SHA1 is nearly collision free, but I cannot figure out how to actually create the hash for my input values. I just need to create the hash, and store the hex value into an array. After some Google searches, I've found OpenSSL documentation directing me to use this:

     #include <openssl/sha.h>
    
     unsigned char *SHA1(const unsigned char *d, unsigned long n,
                      unsigned char *md);
    
     int SHA1_Init(SHA_CTX *c);
     int SHA1_Update(SHA_CTX *c, const void *data,
                      unsigned long len);
     int SHA1_Final(unsigned char *md, SHA_CTX *c);
    

    I believe I should be using either unsigned char *SHA1 or SHA1_Init, but I am not sure what the arguments would be, given x is my input to be hashed. Would someone please clear this up for me? Thanks.