Generate Sha Hash in C++ Using Openssl Library

Generate sha256 with OpenSSL and C++

Here's how I did it:

void sha256_hash_string (unsigned char hash[SHA256_DIGEST_LENGTH], char outputBuffer[65])
{
int i = 0;

for(i = 0; i < SHA256_DIGEST_LENGTH; i++)
{
sprintf(outputBuffer + (i * 2), "%02x", hash[i]);
}

outputBuffer[64] = 0;
}

void sha256_string(char *string, char outputBuffer[65])
{
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, string, strlen(string));
SHA256_Final(hash, &sha256);
int i = 0;
for(i = 0; i < SHA256_DIGEST_LENGTH; i++)
{
sprintf(outputBuffer + (i * 2), "%02x", hash[i]);
}
outputBuffer[64] = 0;
}

int sha256_file(char *path, char outputBuffer[65])
{
FILE *file = fopen(path, "rb");
if(!file) return -534;

unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
SHA256_Init(&sha256);
const int bufSize = 32768;
unsigned char *buffer = malloc(bufSize);
int bytesRead = 0;
if(!buffer) return ENOMEM;
while((bytesRead = fread(buffer, 1, bufSize, file)))
{
SHA256_Update(&sha256, buffer, bytesRead);
}
SHA256_Final(hash, &sha256);

sha256_hash_string(hash, outputBuffer);
fclose(file);
free(buffer);
return 0;
}

It's called like this:

static unsigned char buffer[65];
sha256("string", buffer);
printf("%s\n", buffer);

sha1 example in C using openssl library

Rather than using the SHA1 or SHA256 specific functions, use the EVP_Digest* family of functions which work with any hash.

...

// makes all algorithms available to the EVP* routines
OpenSSL_add_all_algorithms();
// load the error strings for ERR_error_string
ERR_load_crypto_strings();

EVP_MD_CTX hashctx;
//const EVP_MD *hashptr = EVP_get_digestbyname("SHA256");
const EVP_MD *hashptr = EVP_get_digestbyname("SHA1");

EVP_MD_CTX_init(&hashctx);
EVP_DigestInit_ex(&hashctx, hashptr, NULL);

do {
len = fread(buffer, 1, BUFSIZ, f);
EVP_DigestUpdate(&hashctx, buffer, len);
} while (len == BUFSIZ);

unsigned int outlen;
EVP_DigestFinal_ex(&hashctx, buffer, &outlen);
EVP_MD_CTX_cleanup(&hashctx);

fclose(f);

int i;
for (i = 0; i < outlen; ++i)
printf("%02x", buffer[i]);

I've omitted the error checking for brevity. To check for errors, do the following:

if (function_to_check() == 0) {
char errstr[1000];
ERR_error_string(ERR_get_error(), errstr);
printf("error: %s\n", errstr;
}

EDIT:

There were some error in the above code that have been corrected:

  • hashptr was declared EVP_MD *, is now const EVP_MD *.
  • The call to EVP_DigestInit_ex had an extra parenthesis at the end
  • The third parameter to EVP_DigestFinal_ex is specifically given an unsigned int * instead a size_t *, which may not necessarily be the same.
  • Added calls to two OpenSSL initialization functions at the top

sha512: c program using the openSSL library

Yes, this will work. The man page for the SHA family of functions lists the following:

 int SHA256_Init(SHA256_CTX *c);
int SHA256_Update(SHA256_CTX *c, const void *data, size_t len);
int SHA256_Final(unsigned char *md, SHA256_CTX *c);
unsigned char *SHA256(const unsigned char *d, size_t n,
unsigned char *md);

...

int SHA512_Init(SHA512_CTX *c);
int SHA512_Update(SHA512_CTX *c, const void *data, size_t len);
int SHA512_Final(unsigned char *md, SHA512_CTX *c);
unsigned char *SHA512(const unsigned char *d, size_t n,
unsigned char *md);

...

SHA1_Init() initializes a SHA_CTX structure.

SHA1_Update() can be called repeatedly with chunks of the message
to be hashed (len bytes at data).

SHA1_Final() places the message digest in md, which must have space
for SHA_DIGEST_LENGTH == 20 bytes of output, and erases the
SHA_CTX.

The SHA224, SHA256, SHA384 and SHA512 families of functions operate
in the same way as for the SHA1 functions. Note that SHA224 and
SHA256 use a SHA256_CTX object instead of SHA_CTX. SHA384 and
SHA512 use SHA512_CTX. The buffer md must have space for the
output from the SHA variant being used (defined by
SHA224_DIGEST_LENGTH, SHA256_DIGEST_LENGTH, SHA384_DIGEST_LENGTH
and SHA512_DIGEST_LENGTH). Also note that, as for the SHA1()
function above, the SHA224(), SHA256(), SHA384() and SHA512()
functions are not thread safe if md is NULL.

To confirm, let's look at some code segments. First with SHA256:

SHA256_CTX ctx;
unsigned char buffer[512];

char *str = "this is a test";
int len = strlen(str);

strcpy(buffer,str);

SHA256_Init(&ctx);
SHA256_Update(&ctx, buffer, len);
SHA256_Final(buffer, &ctx);

fwrite(&buffer,32,1,stdout);

When run as:

./test1 | od -t x1

Outputs:

0000000 2e 99 75 85 48 97 2a 8e 88 22 ad 47 fa 10 17 ff
0000020 72 f0 6f 3f f6 a0 16 85 1f 45 c3 98 73 2b c5 0c
0000040

Which matches the output of:

echo -n "this is a test" | openssl sha256

Which is:

(stdin)= 2e99758548972a8e8822ad47fa1017ff72f06f3ff6a016851f45c398732bc50c

Now the same code with the changes you suggested:

SHA512_CTX ctx;
unsigned char buffer[512];

char *str = "this is a test";
int len = strlen(str);

strcpy(buffer,str);

SHA512_Init(&ctx);
SHA512_Update(&ctx, buffer, len);
SHA512_Final(buffer, &ctx);

fwrite(&buffer,64,1,stdout);

The output when passed through "od" gives us:

0000000 7d 0a 84 68 ed 22 04 00 c0 b8 e6 f3 35 ba a7 e0
0000020 70 ce 88 0a 37 e2 ac 59 95 b9 a9 7b 80 90 26 de
0000040 62 6d a6 36 ac 73 65 24 9b b9 74 c7 19 ed f5 43
0000060 b5 2e d2 86 64 6f 43 7d c7 f8 10 cc 20 68 37 5c
0000100

Which matches the output of:

echo -n "this is a test" | openssl sha512 

Which is:

(stdin)= 7d0a8468ed220400c0b8e6f335baa7e070ce880a37e2ac5995b9a97b809026de626da636ac7365249bb974c719edf543b52ed286646f437dc7f810cc2068375c

C++: Efficiently get Sha256 digest into OpenSSL Bignum?

At the end I ended up using BN_bin2bn() to convert a uint8_t into a BigNum.

#include <openssl/bn.h>

void Crypto::Sha256 (const std::string &p_Data, BIGNUM* hash)
{
uint8_t digestBuffer[256];
SHA256_CTX context;

SHA256_Init (&context);
SHA256_Update (&context, p_Data.c_str (), p_Data.length ());
SHA256_Final (digestBuffer, &context);

BN_bin2bn (digestBuffer, 256, hash);
}

HMAC-SHA256 in C with OpenSSL - how to get a correct output

You are getting the same result, you are just printing it as decimals whereas the online tool is outputting hexadecimal.

204 decimal is CC in hecadecimal, 219 is DB etc.

Try

for (unsigned int i = 0; i < resultlen; i++){
printf("%02hhX", result[i]); // or just "%02X" if you are not using C11 or later
}

instead.

Correctly getting sha-1 for files using openssl

If you get trouble reading the file contents, prior to invoking the hash function code, then your problem is not related to hashing.

You should use the standard fopen() function, rather than _tfopen(). In C, things which begin with an underscore character are often best avoided. Especially since _tfopen() seems to map to either fopen() or the Windows-specific _wfopen() depending on whether so-called "unicode support" is activated. Alternatively, in a purely Windows application, you may rely on Win32 functions such as CreateFile().

Reading the whole file in memory and then hashing it is crude. It will fail to process files which are larger than available RAM, for instance. Also, in order to know the file size, you have to seek into it, which is not reliable (there may be pseudo-files which are actually pipes into some data-generating process, for which seeking is not possible). Hash functions can process data by chunks; you should use a small buffer (8 kB is the traditional size) and employ the SHA1_Init(), SHA1_Update() and SHA1_Final() functions.

fread() does not necessarily read as much data as you requested. And this is not an error.

When you call SHA1(), you use strlen() on your buffer, which is bogus. strlen() returns the length of a character string; in plain words, the number of bytes until the next byte of value zero. Many files contain bytes of value 0. And if the file does not, then there is no guarantee that your buffer contains any byte of value 0, so that the call to strlen() may end up reading memory outside of the allocated buffer (this is bad). Since you went to the trouble of obtaining the file length and allocating a buffer that big, you should at least use that length instead of trying to recompute it with a function which does not do that.

To sum up: your code should look like that (untested):

/*
* Hash a file, which name is given. Hash output is written out in
* buffer "out[]". The hash output consists in exactly 20 bytes.
* On success, 0 is returned; on error, returned value is -1 and
* out[] is unaltered.
*/
int
do_sha1_file(char *name, unsigned char *out)
{
FILE *f;
unsigned char buf[8192];
SHA_CTX sc;
int err;

f = fopen(name, "rb");
if (f == NULL) {
/* do something smart here: the file could not be opened */
return -1;
}
SHA1_Init(&sc);
for (;;) {
size_t len;

len = fread(buf, 1, sizeof buf, f);
if (len == 0)
break;
SHA1_Update(&sc, buf, len);
}
err = ferror(f);
fclose(f);
if (err) {
/* some I/O error was encountered; report the error */
return -1;
}
SHA1_Final(out, &sc);
return 0;
}

And do not forget to include the relevant file headers ! (<stdio.h>, and the sha.h from OpenSSL)

MD5/ SHA1 hash with salt using openssl in c programming

Salting is just concatenating salt to data in before applying hash function.
Salt should be random and never twice the same, goal is to defeat precomputed rainbow tables. Salt should be stored together with the hash when checking of data ( password ) is done.

Based on your code, concanating salt in front of data is (untested whatsoever) :

bool simpleSHA256(void * salt, unsigned long salt_length, void* input, unsigned long length, unsigned char* md) 
{
SHA256_CTX context;
if(!SHA256_Init(&context))
return false;

// first apply salt
if(!SHA256_Update(&context, (unsigned char*)salt, salt_length))
return false;

// continue with data...
if(!SHA256_Update(&context, (unsigned char*)input, length))
return false;

if(!SHA256_Final(md, &context))
return false;

return true;
}


Related Topics



Leave a reply



Submit