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.
If you have all of your data at once, just use the
SHA1
function: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:
Calculate hash like this
Finally you can decode hash to human-readable form by code like this.
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.
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:
They're two different ways to achieve the same thing.
Specifically, you either use
SHA_Init
, thenSHA_Update
as many times as necessary to pass your data through and thenSHA_Final
to get the digest, or youSHA1
.The reason for two modes is that when hashing large files it is common to read the file in chunks, as the alternative would use a lot of memory. Hence, keeping track of the
SHA_CTX
- the SHA context - as you go allows you to get around this. The algorithm internally also fits this model - that is, data is passed in block at a time.The
SHA
method should be fairly straightforward. The other works like this:Crucially, at the end
md
will contain the binary digest, not a hexadecimal representation - it's not a string and shouldn't be used as one.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 andmd
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.