I am trying to use md5 code to calculate checksums of file. Now the given function prints out the (previously calculated) checksum on screen, but I want to store it in a variable, to be able to compare it later on.
I guess the main problem is that I want to store the content of an array in one variable.
How can I manage that?
Probably this is a very stupid question, but maybe somone can help.
Below is the function to print out the value. I want to modify it to store the result in one variable.
static void MDPrint (MD5_CTX* mdContext)
{
int i;
for (i = 0; i < 16; i++)
{
printf ("%02x", mdContext->digest[i]);
} // end of for
} // end of function
For reasons of completeness the used struct:
/* typedef a 32 bit type */
typedef unsigned long int UINT4;
/* Data structure for MD5 (Message Digest) computation */
typedef struct {
UINT4 i[2]; /* number of _bits_ handled mod 2^64 */
UINT4 buf[4]; /* scratch buffer */
unsigned char in[64]; /* input buffer */
unsigned char digest[16]; /* actual digest after MD5Final call */
} MD5_CTX;
and the used function to calculate the checksum:
static int MDFile (char* filename)
{
FILE *inFile = fopen (filename, "rb");
MD5_CTX mdContext;
int bytes;
unsigned char data[1024];
if (inFile == NULL) {
printf ("%s can't be opened.\n", filename);
return -1;
} // end of if
MD5Init (&mdContext);
while ((bytes = fread (data, 1, 1024, inFile)) != 0)
MD5Update (&mdContext, data, bytes);
MD5Final (&mdContext);
MDPrint (&mdContext);
printf (" %s\n", filename);
fclose (inFile);
return 0;
}
Declare an array and memcpy the result.
Example:
unsigned char old_md5_dig[16]; // <-- binary format
...
MD5_CTX mdContext;
MD5Init(&mdContext);
MD5Update(&mdContext, data, bytes);
MD5Final(&mdContext);
memcpy(old_md5_dig, mdContext.digest, 16); // <--
Edit: to compare the previous with the new md5 hash you can use memcmp,
if (memcmp(old_md5_dig, mdContext.digest, 16)) {
// different hashes
}
Just pass a char buffer and its size to this function:
static void MDGen (mdContext, buf, size)
MD5_CTX *mdContext;
char *buf;
size_t size;
{
int i;
int minSize = 33; // 16 pairs of hex digits plus terminator
if ((buf != NULL) && (size >= minSize))
{
memset(buf, 0, size);
for (i = 0; i < 16; i++)
{
snprintf(buf + (i*2), size - (i*2), "%02x", mdContext->digest[i]);
}
}
}
You can define a variable:
char **md5sums;
You will then need to modify MDPrint to instead return a malloced null-terminated string with the 32 hex digits. You can basically reuse your existing loop, but with sprintf instead.
Then have main add each md5sum (a char*) to md5sums. You will need to use realloc to allocate memory for md5sums because you don't know the number of elements up front.
It should be:
static char* MDString (mdContext)
MD5_CTX *mdContext;
{
int i;
char *digest = malloc(sizeof(char) * 33);
if(digest == NULL)
{
return NULL;
}
for (i = 0; i < 16; i++)
{
sprintf(digest + (i * 2), "%02x", mdContext->digest[i]);
}
return digest;
}
Also, you should modify your code by editing your question. And why are you using K&R syntax?
EDIT: I fixed some incorrect counts.
Since you want to duplicate, store, compare, free and probably more the MD5 digest, just create a md5_t type and write appropriate functions to manipulate it, ie :
typedef char md5_t[16];
md5_t *md5_new( MD5_CTX *pMD5Context )
{
md5_t *pMD5 = malloc( sizeof( md5_t ) );
memcpy( pMD5, pMD5Context->digest, 16 );
return pMD5 ;
}
int md5_cmp( md5_t *pMD5A, md5_t *pMD5B )
{
return memcmp( pMD5A, pMD5B, 16 );
}
void md5_print( md5_t *pMD5 )
{
...
}
void md5_free( md5_t *pMD5 )
{
free( pMD5 );
}
And so on ... Next, create a type for your MD5 array and simple functions to manipulate it :
typedef struct md5array_t {
unsigned int uSize ;
md5_t **ppMD5 ;
}
md5array_t *md5array_new()
{
md5array_t *pArray = malloc( sizeof( md5array_t );
pArray->uSize = 0 ;
pArray->ppMD5 = NULL ;
}
md5array_t *md5array_add( md5array_t *pArray, md5_t *pMD5 )
{
pArray->uSize ++ ;
pArray = realloc( pArray, pArray->uSize + sizeof( md5_t * ) );
pArray->ppMD5[ pArray->uSize-1 ] = pMD5 ;
}
md5_t *md5array_get( md5array_t *pArray, unsigned int uIndex )
{
return pArray->ppMD5[ uIndex ];
}
void md5array_free( md5array_t *pArray }
{
/* I let you find what to write here.
Be sure to read AND understand the previous
functions. */
}
To resume : create a type and the functions you need to manipulate it as soon as you want to do more than one operation with a datum. You don't need to create a real, generic type with full-blown functions representing as many operations you can imagine on that type : just code what you need. For example, in the md5array_t, you can add a md5_t * but you cannot delete it (unless you write the function void md5array_del( md5array_t *pArray *, int iIndex ).
P.S. : my C code is here to "illustrate" my point of view, not to be useable by just copying/pasting it as is ...
Store it as a string and then use strcmp() to compare.
Just leave in an array!
You don't have you store it in variable; because it is ALREADY in a variable..
Just create global variable, store MD5 hash in it and compare to it later.
What you need is MD5IsEqual function, which takes 2 arrays like this.
int MD5IsEqual(unsigned char *x, unsigned char* y)
{
int i;
for(i=0; i<16;i++)
if(x[i] != y[i])
return 0;
return 1;
}
Why not make the function
MD5File(char * filename, unsigned char *digest){
/* as before */
memcpy(digest, mdContext->digest, 16);
return;
}
so that outside the function you have access to the digest (after printing it) ?
The digest is just an array of 16 unsigned char...
You know where the sum is stored by the way you print it: through ->digest[i]. Which is defined like
unsigned char digest[16];
So you basically just need to copy these 16 unsigned char in another array of unsigned char (at least 16 unsigned char long). The function memcpy can do it. If you need comparing two sums, you can use memcmp (the comparing size will be 16*sizeof(unsigned char) which is 16, being sizeof(unsigned char) 1.
Related
I have these functions
char *hash(char *stringa, char *tipohash) {
if (strcmp(tipohash, "md5") == 0) {
stringa = md5(stringa);
}
return stringa;
}
char *md5(char *stringa) {
unsigned char risultato[MD5_DIGEST_LENGTH];
int i;
char *hashfinale = malloc(sizeof(char) * MD5_DIGEST_LENGTH * 2);
MD5((const unsigned char *)stringa, strlen(stringa), risultato);
for (i = 0; i < MD5_DIGEST_LENGTH; i++) {
sprintf(hashfinale + 2 * i, "%02x", risultato[i]);
}
return (char *)hashfinale;
}
How I can return (char *)hashfinale doing the free without losing the value of the string?
This is the caller
char *hashlinea = hash(stringa, hashType);
There are basically two ways to solve the problem, and none of them involves your code calling free.
The first way is to just do nothing different from now, except to add documentation so the user of your hash function knows that the code must call free on the returned pointer:
// This is the code using your function
char *hashlinea = hash(stringa,hashType);
// Some code using hashlinea
free(hashlinea);
The second way is to pass a pointer to an existing array, and your code use that array instead of allocating it using malloc:
char hashlinea[MD5_DIGEST_LENGTH*2];
hash(stringa, hashType, hashlinea);
For this your hash function needs to pass on the third argument to the md5 function, which should use it instead of allocating memory:
char *md5(char *stringa, char *hashfinale){
unsigned char risultato[MD5_DIGEST_LENGTH];
int i;
// No memory allocation here
MD5((const unsigned char *)stringa, strlen(stringa), risultato);
for(i = 0; i < MD5_DIGEST_LENGTH; i++) {
sprintf(hashfinale + 2*i,"%02x",risultato[i]);
}
return hashfinale;
}
It is not possible. IMO it is better to pass the pointer to the buffer. The caller will be responsible for the memory management
char *md5(char *stringa, char *hashfinale){
...
}
There is a problem in your md5 function: the size allocated for the MD5 hash must be one byte longer for the null terminator:
char *hashfinale = malloc(sizeof(char) * (MD5_DIGEST_LENGTH * 2 + 1));
Note that in C (and C++) sizeof(char) is 1 by definition, so you could just write:
char *hashfinale = malloc(MD5_DIGEST_LENGTH * 2 + 1);
Regarding your question, hash returns either its argument or an allocated object. This is a problem for memory management, as yo may not know later in the program if the return value must be freed or not. Passing the destination array for the hash string is a better alternative, otherwise you should duplicate the string so the return value of hash can be unconditionally freed:
char *md5(const char *stringa) {
unsigned char risultato[MD5_DIGEST_LENGTH];
int i;
char *hashfinale = malloc(MD5_DIGEST_LENGTH * 2 + 1);
MD5((const unsigned char *)stringa, strlen(stringa), risultato);
for (i = 0; i < MD5_DIGEST_LENGTH; i++) {
sprintf(hashfinale + 2 * i, "%02x", risultato[i]);
}
return hashfinale;
}
// always free the return value
char *hash(const char *stringa, const char *tipohash) {
if (!strcmp(tipohash, "md5")) {
return md5(stringa);
} else {
return strdup(stringa);
}
}
Program crashing when freeing allocated memory: "Heap block at X modified at Y past requested size of 21".
Running function getUstr, crashes on free(uStr).
Can someone please help me find where am I using unallocated memory?
Thank you!
int HexToUChars(char* hexStr, unsigned char **str){
int i, n;
int strLen = strlen(hexStr)/2;
for (i = 0; i < (int)strLen; i++) {
sscanf_s(hexStr + 2 * i*sizeof(unsigned char), "%02X", *str+i*sizeof(unsigned char));
}
return 0;
}
int getUStr(){
char *hexStr = "E7CA7905DD060F0E437C885BF13DED9243B1D2BD94CB11223DA71360A8F7D2D4";
unsigned char *uStr;
size_t strLen = (size_t)strlen(hexStr) / 2;
uStr = calloc((strLen + 1), sizeof(unsigned char));
if (uStr != NULL){
HexToUChars(hexStr, &uStr);
free(uStr);//Error : Heap block at X modified at Y past requested size of 21
}
}
For sscanf() and friends, %02X expects a pointer to an unsigned int, but you're giving it a pointer to an unsigned char. If an unsigned int is, say, 4 bytes on your system, then you're going to write past the end of your allocated memory on the last couple of iterations through that loop.
You should provide a pointer to a (local) unsigned int to sscanf_s(), and then assign the value of that to your unsigned char.
there were several errors in the presented code.
those errors are fixed here
I did add a few $includes, etc so the file would compile
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int HexToUChars( const char *, unsigned char * );
int getUStr( void );
int HexToUChars(const char* pHexStr, unsigned char *pStr)
{
int i = 0; // loop index
//int n; // this raises a compiler warning about unused variable
// the strLen is using a reserved word, with only a capitalization change,
// I.E. very poor program practice
int hexStrLen = (int)strlen(pHexStr) >> 1; // this assumes that hexStr is an even number of bytes
for (i = 0; i < hexStrLen; i++)
{
pStr[i] = pHexStr[2*i] - '0';
pStr[i] += pHexStr[(2*i)+1] - '0';
} // end for
return 1;
} // end function: HexToUChars
int getUStr()
{
const char* pHexStr = "E7CA7905DD060F0E437C885BF13DED9243B1D2BD94CB11223DA71360A8F7D2D4";
unsigned char *pStr;
int hexStrLen = strlen(pHexStr) / 2;
if( NULL == (pStr = calloc( (hexStrLen + 1), sizeof(unsigned char) ) ) )
{
perror( "calloc failed" );
exit( EXIT_FAILURE );
}
// implied else, calloc successful
HexToUChars(pHexStr, pStr);
if( strlen((const char*)pStr) != hexStrLen )
{
perror( "problem in HexToUChars");
}
printf( "%s", pStr );
free(pStr);
return(0); // without this, compiler raises warning about no return statement
}
I want to parse a character buffer and store it in a data structure.
The 1st 4 bytes of the buffer specifies the name, the 2nd four bytes specifies the length (n) of the value and the next n bytes specifies the value.
eg: char *buff = "aaaa0006francebbbb0005swisscccc0013unitedkingdom"
I want to extract the name and the value from the buffer and store it a data structure.
eg: char *name = "aaaa"
char *value = "france"
char *name = "bbbb"
char *value = "swiss"
After storing, I should be able to access the value from the data structure by using the name.
What data structure should I use?
EDIT (from comment):
I tried the following:
struct sample {
char string[4];
int length[4];
char *value; };
struct sample s[100];
while ( *buf ) {
memcpy(s[i].string, buf, 4);
memcpy(s[i].length, buf+4, 4);
memcpy(s[i].value, buf+8, s.length);
buf += (8+s.length);
}
Should I call memcpy thrice? Is there a way to do it by calling memcpy only once?
How about not using memcpy at all?
typedef struct sample {
char name[4];
union
{
char length_data[4];
unsigned int length;
};
char value[];
} sample_t;
const char * sample_data = "aaaa\6\0\0\0francebbbb\5\0\0\0swisscccc\15\0\0\0unitedkingdom";
void main()
{
sample_t * s[10];
const char * current = sample_data;
int i = 0;
while (*current)
{
s[i] = (sample_t *) current;
current += (s[i])->length + 8;
i++;
}
// Here, s[0], s[1] and s[2] should be set properly
return;
}
Now, you never specify clearly whether the 4 bytes representing the length contain the string representation or the actual binary data; if it's four characters that needs to run through atoi() or similar then you need to do some post-processing like
s[i]->length = atoi(s[i]->length_data)
before the struct is usable, which in turn means that the source data must be writeable and probably copied locally. But even then you should be able to copy the whole input buffer at once instead of chopping it up.
Also, please note that this relies on anything using this struct honors the length field rather than treating the value field as a null-terminated string.
Finally, using binary integer data like this is obviously architecture-dependent with all the implications that follows.
To expand on your newly provided info, this will work better:
struct sample {
char string[4];
int length;
char *value; };
struct sample s[100];
while ( *buf && i < 100) {
memcpy(s[i].string, buf, 4);
s[i].length = atoi(buf+4);
s[i].value = malloc(s[i].length);
if (s[i].value)
{
memcpy(s[i].value, buf+8, s[i].length);
}
buf += (8+s[i].length);
i++;
}
I would do something like that:
I will define a variable length structure, like this:
typedef struct {
char string[4];
int length[4];
char value[0] } sample;
now , while parsing, read the string and length into temporary variables.
then, allocate enough memory for the structure.
uint32_t string = * ( ( uint32_t * ) buffer );
uint32_t length = * ( ( uint32_t * ) buffer + 4);
sample * = malloc(sizeof(sample) + length);
// Check here for malloc errors...
* ( (uint32_t *) sample->string) = string;
* ( (uint32_t *) sample->length) = length;
memcpy(sample->value, ( buffer + 8 ), length);
This approach, keeps the entire context of the buffer in one continuous memory structure.
I use it all the time.
How can I implement a substring function such as the following that returns the substring but without using malloc() in the process so I don't have to worry about freeing the associated memory elsewhere in my code using the free() function. Is this even possible?
const char *substring(const char *string, int position, int length)
{
char *pointer;
int c;
pointer = malloc(length+1);
if (pointer == NULL)
{
printf("Unable to allocate memory.\n");
exit(EXIT_FAILURE);
}
for (c = 0 ; c < position -1 ; c++)
string++;
for (c = 0 ; c < length ; c++)
{
*(pointer+c) = *string;
string++;
}
*(pointer+c) = '\0';
return substr;
}
UPDATE: 30 DEC 2012
Having considered all the answers and comments it's clear that essentially what I'm trying to do is create a dynamically sized array (i.e. the substring) and that is not possible in C without somewhere along the way having to use some kind of malloc() function and a subsequent free() call on the substring pointer or without the aid of a garbage collector. I attempted to integrate the libgc garbage collector as kindly suggested by #elhadi but so far have not been able to get this to work in my Xcode project. So I have opted to stick with using the following code with malloc() and free().
char * subStr(const char* srcString, const int offset, const int len)
{
char * sub = (char*)malloc(len+1);
memcpy(sub, srcString + offset, len);
sub[len] = 0;
return sub;
}
int main()
{
const char * message = "hello universe";
char * sub = subStr( message, 6, 8 );
printf( "substring: [%s]", sub );
free(sub);
}
I see two options:
If you can destroy the source string (usually a bad thing):
{
string[ position + length] = 0;
return & string[ position ];
}
Note: (see Cole Johnsons note: free no longer works on the returned pointer!)
If you can't modify the source string:
Modify your methods signature so that the caller has to worry about it:
const char *substring(const char *source, char* destination, int position, int length)
And put the modified string into destination (and return it).
And do not even think about this:
const char *substring(const char *string, int position, int length)
{
char *pointer;
int c;
static char modifiedString[256];
...
return modifiedString;
}
Using a static variable inside the function for the modified results...
(This is not thread-safe (not re-entrant!) )
Use a local buffer (an auto array) and a function like this:
void substr(char *dst, const char *src, size_t loc, size_t len)
{
memcpy(dst, src + loc, len);
dst[len] = 0;
}
Call it like this:
const size_t size = 3;
char buf[size + 1]; // this is an auto array, it will be "freed" at the end of the scope
substr(buf, "abcdFOObar", 4, size);
Always ensure the buffer is at least len + 1 bytes long to avoid buffer overflow errors.
const char *substring(const char *string, char *substr, int position, int length)
{
int c;
for (c = 0 ; c < position -1 ; c++)
string++;
for (c = 0 ; c < length ; c++)
{
*(substr+c) = *string;
string++;
}
*(substr+c) = '\0';
return substr;
}
calling function...
int main(int argc, char * argv[]) {
char substr[10];
substring("hello! World", &substr[0], 2, 4);
}
The best way to do it is:
typedef struct vstr_t {
char *s;
int len;
} vstr_t;
#define vstr_set(d, l) \
({ \
vstr_t vs = {.s = d, .len = l}; \
\
vs; \
})
#define vstr_fmt_arg(vs) (vs).len, (vs).s
int main()
{
const char *message = "hello universe";
printf( "substring: [%.*s]\n", vstr_fmt_arg(vstr_set(smpl + 6, 8)));
return 0;
}
You can use a garbage collector, you allocate the memory the first time, the garbage collector will free the memory when no needed.
you should include
#include "gc.h"
in the main you should make something like
GC_INIT(); /* Optional on Linux/X86;*/
and your substr function is:
char *substr(const char* buffer, const int offset, int len)
{
char sub = (char*)GC_MALLOC(len+1);
memcpy(sub, buffer + offset, len);
sub[len] = 0;
return sub;
}
you should link with libgc.a
I've found some md5 code that consists of the following prototypes...
I've been trying to find out where I have to put the string I want to hash, what functions I need to call, and where to find the string once it has been hashed. I'm confused with regards to what the uint32 buf[4] and uint32 bits[2] are in the struct.
struct MD5Context {
uint32 buf[4];
uint32 bits[2];
unsigned char in[64];
};
/*
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
void MD5Init(struct MD5Context *context);
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len);
/*
* Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first)
*/
void MD5Final(unsigned char digest[16], struct MD5Context *context);
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
* reflect the addition of 16 longwords of new data. MD5Update blocks
* the data and converts bytes into longwords for this routine.
*/
void MD5Transform(uint32 buf[4], uint32 const in[16]);
I don't know this particular library, but I've used very similar calls. So this is my best guess:
unsigned char digest[16];
const char* string = "Hello World";
struct MD5Context context;
MD5Init(&context);
MD5Update(&context, string, strlen(string));
MD5Final(digest, &context);
This will give you back an integer representation of the hash. You can then turn this into a hex representation if you want to pass it around as a string.
char md5string[33];
for(int i = 0; i < 16; ++i)
sprintf(&md5string[i*2], "%02x", (unsigned int)digest[i]);
Here's a complete example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(__APPLE__)
# define COMMON_DIGEST_FOR_OPENSSL
# include <CommonCrypto/CommonDigest.h>
# define SHA1 CC_SHA1
#else
# include <openssl/md5.h>
#endif
char *str2md5(const char *str, int length) {
int n;
MD5_CTX c;
unsigned char digest[16];
char *out = (char*)malloc(33);
MD5_Init(&c);
while (length > 0) {
if (length > 512) {
MD5_Update(&c, str, 512);
} else {
MD5_Update(&c, str, length);
}
length -= 512;
str += 512;
}
MD5_Final(digest, &c);
for (n = 0; n < 16; ++n) {
snprintf(&(out[n*2]), 16*2, "%02x", (unsigned int)digest[n]);
}
return out;
}
int main(int argc, char **argv) {
char *output = str2md5("hello", strlen("hello"));
printf("%s\n", output);
free(output);
return 0;
}
As other answers have mentioned, the following calls will compute the hash:
MD5Context md5;
MD5Init(&md5);
MD5Update(&md5, data, datalen);
MD5Final(digest, &md5);
The purpose of splitting it up into that many functions is to let you stream large datasets.
For example, if you're hashing a 10GB file and it doesn't fit into ram, here's how you would go about doing it. You would read the file in smaller chunks and call MD5Update on them.
MD5Context md5;
MD5Init(&md5);
fread(/* Read a block into data. */)
MD5Update(&md5, data, datalen);
fread(/* Read the next block into data. */)
MD5Update(&md5, data, datalen);
fread(/* Read the next block into data. */)
MD5Update(&md5, data, datalen);
...
// Now finish to get the final hash value.
MD5Final(digest, &md5);
To be honest, the comments accompanying the prototypes seem clear enough. Something like this should do the trick:
void compute_md5(char *str, unsigned char digest[16]) {
MD5Context ctx;
MD5Init(&ctx);
MD5Update(&ctx, str, strlen(str));
MD5Final(digest, &ctx);
}
where str is a C string you want the hash of, and digest is the resulting MD5 digest.
It would appear that you should
Create a struct MD5context and pass it to MD5Init to get it into a proper starting condition
Call MD5Update with the context and your data
Call MD5Final to get the resulting hash
These three functions and the structure definition make a nice abstract interface to the hash algorithm. I'm not sure why you were shown the core transform function in that header as you probably shouldn't interact with it directly.
The author could have done a little more implementation hiding by making the structure an abstract type, but then you would have been forced to allocate the structure on the heap every time (as opposed to now where you can put it on the stack if you so desire).
All of the existing answers use the deprecated MD5Init(), MD5Update(), and MD5Final().
Instead, use EVP_DigestInit_ex(), EVP_DigestUpdate(), and EVP_DigestFinal_ex(), e.g.
// example.c
//
// gcc example.c -lssl -lcrypto -o example
#include <openssl/evp.h>
#include <stdio.h>
#include <string.h>
void bytes2md5(const char *data, int len, char *md5buf) {
// Based on https://www.openssl.org/docs/manmaster/man3/EVP_DigestUpdate.html
EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
const EVP_MD *md = EVP_md5();
unsigned char md_value[EVP_MAX_MD_SIZE];
unsigned int md_len, i;
EVP_DigestInit_ex(mdctx, md, NULL);
EVP_DigestUpdate(mdctx, data, len);
EVP_DigestFinal_ex(mdctx, md_value, &md_len);
EVP_MD_CTX_free(mdctx);
for (i = 0; i < md_len; i++) {
snprintf(&(md5buf[i * 2]), 16 * 2, "%02x", md_value[i]);
}
}
int main(void) {
const char *hello = "hello";
char md5[33]; // 32 characters + null terminator
bytes2md5(hello, strlen(hello), md5);
printf("%s\n", md5);
}