if this helped you, please donate! (bill.sherif@gmail.com)
Here’s an implementation of the MD5 algorithm in C++.
Simply copy and paste into a file “md5.h”. Only dependencies are on <string.h> and <stdio.h>.
Originally adapted from the C reference implementation on this page
Tested in Visual Studio 2010.
Sample use:
Main.cpp
#include "md5.h" int main() { MD5 md5 ; puts( md5.digestString( "HELLO THERE I AM MD5!" ) ) ; // print the digest for a binary file on disk. puts( md5.digestFile( "C:\\WINDOWS\\notepad.exe" ) ) ; return 0; }
md5.h
(No .cpp file)
#ifndef MD5_H #define MD5_H // Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All // rights reserved. // License to copy and use this software is granted provided that it // is identified as the "RSA Data Security, Inc. MD5 Message-Digest // Algorithm" in all material mentioning or referencing this software // or this function. // // License is also granted to make and use derivative works provided // that such works are identified as "derived from the RSA Data // Security, Inc. MD5 Message-Digest Algorithm" in all material // mentioning or referencing the derived work. // // RSA Data Security, Inc. makes no representations concerning either // the merchantability of this software or the suitability of this // software for any particular purpose. It is provided "as is" // without express or implied warranty of any kind. // // These notices must be retained in any copies of any part of this // documentation and/or software. // The original md5 implementation avoids external libraries. // This version has dependency on stdio.h for file input and // string.h for memcpy. #include <stdio.h> #include <string.h> #pragma region MD5 defines // Constants for MD5Transform routine. #define S11 7 #define S12 12 #define S13 17 #define S14 22 #define S21 5 #define S22 9 #define S23 14 #define S24 20 #define S31 4 #define S32 11 #define S33 16 #define S34 23 #define S41 6 #define S42 10 #define S43 15 #define S44 21 static unsigned char PADDING[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // F, G, H and I are basic MD5 functions. #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) #define G(x, y, z) (((x) & (z)) | ((y) & (~z))) #define H(x, y, z) ((x) ^ (y) ^ (z)) #define I(x, y, z) ((y) ^ ((x) | (~z))) // ROTATE_LEFT rotates x left n bits. #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. // Rotation is separate from addition to prevent recomputation. #define FF(a, b, c, d, x, s, ac) { \ (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define GG(a, b, c, d, x, s, ac) { \ (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define HH(a, b, c, d, x, s, ac) { \ (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define II(a, b, c, d, x, s, ac) { \ (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #pragma endregion typedef unsigned char BYTE ; // POINTER defines a generic pointer type typedef unsigned char *POINTER; // UINT2 defines a two byte word typedef unsigned short int UINT2; // UINT4 defines a four byte word typedef unsigned long int UINT4; // convenient object that wraps // the C-functions for use in C++ only class MD5 { private: struct __context_t { UINT4 state[4]; /* state (ABCD) */ UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } context ; #pragma region static helper functions // The core of the MD5 algorithm is here. // MD5 basic transformation. Transforms state based on block. static void MD5Transform( UINT4 state[4], unsigned char block[64] ) { UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; Decode (x, block, 64); /* Round 1 */ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ /* Round 2 */ GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ /* Round 3 */ HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ /* Round 4 */ II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; // Zeroize sensitive information. memset((POINTER)x, 0, sizeof (x)); } // Encodes input (UINT4) into output (unsigned char). Assumes len is // a multiple of 4. static void Encode( unsigned char *output, UINT4 *input, unsigned int len ) { unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 4) { output[j] = (unsigned char)(input[i] & 0xff); output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); } } // Decodes input (unsigned char) into output (UINT4). Assumes len is // a multiple of 4. static void Decode( UINT4 *output, unsigned char *input, unsigned int len ) { unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 4) output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); } #pragma endregion public: // MAIN FUNCTIONS MD5() { Init() ; } // MD5 initialization. Begins an MD5 operation, writing a new context. void Init() { context.count[0] = context.count[1] = 0; // Load magic initialization constants. context.state[0] = 0x67452301; context.state[1] = 0xefcdab89; context.state[2] = 0x98badcfe; context.state[3] = 0x10325476; } // MD5 block update operation. Continues an MD5 message-digest // operation, processing another message block, and updating the // context. void Update( unsigned char *input, // input block unsigned int inputLen ) // length of input block { unsigned int i, index, partLen; // Compute number of bytes mod 64 index = (unsigned int)((context.count[0] >> 3) & 0x3F); // Update number of bits if ((context.count[0] += ((UINT4)inputLen << 3)) < ((UINT4)inputLen << 3)) context.count[1]++; context.count[1] += ((UINT4)inputLen >> 29); partLen = 64 - index; // Transform as many times as possible. if (inputLen >= partLen) { memcpy((POINTER)&context.buffer[index], (POINTER)input, partLen); MD5Transform (context.state, context.buffer); for (i = partLen; i + 63 < inputLen; i += 64) MD5Transform (context.state, &input[i]); index = 0; } else i = 0; /* Buffer remaining input */ memcpy((POINTER)&context.buffer[index], (POINTER)&input[i], inputLen-i); } // MD5 finalization. Ends an MD5 message-digest operation, writing the // the message digest and zeroizing the context. // Writes to digestRaw void Final() { unsigned char bits[8]; unsigned int index, padLen; // Save number of bits Encode( bits, context.count, 8 ); // Pad out to 56 mod 64. index = (unsigned int)((context.count[0] >> 3) & 0x3f); padLen = (index < 56) ? (56 - index) : (120 - index); Update( PADDING, padLen ); // Append length (before padding) Update( bits, 8 ); // Store state in digest Encode( digestRaw, context.state, 16); // Zeroize sensitive information. memset((POINTER)&context, 0, sizeof (context)); writeToString() ; } /// Buffer must be 32+1 (nul) = 33 chars long at least void writeToString() { int pos ; for( pos = 0 ; pos < 16 ; pos++ ) sprintf( digestChars+(pos*2), "%02x", digestRaw[pos] ) ; } public: // an MD5 digest is a 16-byte number (32 hex digits) BYTE digestRaw[ 16 ] ; // This version of the digest is actually // a "printf'd" version of the digest. char digestChars[ 33 ] ; /// Load a file from disk and digest it // Digests a file and returns the result. char* digestFile( char *filename ) { Init() ; FILE *file; int len; unsigned char buffer[1024] ; if( (file = fopen (filename, "rb")) == NULL ) printf( "%s can't be opened\n", filename ) ; else { while( len = fread( buffer, 1, 1024, file ) ) Update( buffer, len ) ; Final(); fclose( file ); } return digestChars ; } /// Digests a byte-array already in memory char* digestMemory( BYTE *memchunk, int len ) { Init() ; Update( memchunk, len ) ; Final() ; return digestChars ; } // Digests a string and prints the result. char* digestString( char *string ) { Init() ; Update( (unsigned char*)string, strlen(string) ) ; Final() ; return digestChars ; } } ; #endif
35 Comments
Are you sute its right?
I just tested with md5sum. Files: Notepad.exe (Version 6.1.7600.16385) has checksum
f2c7bb8acc97f92e987a2d4087d021b1 (both code provided and md5sum)
The text “HELLO THERE I AM MD5!” (without quotes) generates checksum 7f46e34f077fe20a8a4c3190f0bddbf0, in both md5sum and the text processor in the code above.
The code above generates the exact same result as MD5Sum.
If you are putting text in a text file, be sure you didn’t enter any extra newlines etc before EOF.
When I use this piece of code I do get a hash but it does not match with other programs I am using. For example, the hash obtained from the PHP function MD5_file() and this digest_file() is not the same.
Any reason why the same algorithm would give different results ?
Nvm, it was me screwing up ;)
Thanks for this snippet!
char very slow
std::string fast in Visual Studio and GC++
@Pandora:
1) Generally char* is faster than std::string on all machines and OS’s
2) The underlying MD5 library is written in C, so it uses char arrays
3) You can easily take the outputted string and wrap it up in a std::string.
Thanks!
I’m looking for cpp md5 code like this!
Can I use it in my program?
What about SHA-265 C++ implementation
When trying to use this code
char input;
cin >> input;
puts( md5.digestString(input) ) ;
I get the following error:
error C2664: ‘MD5::digestString’ : cannot convert parameter 1 from ‘char’ to ‘char *’
I’ve tried googling and different types of input. I’m in need for some help, please.
Matt, you will need to get a pointer to it. So doing this will make it work:
char input;
cin >> input;
char* inputpointer = &input;
puts( md5.digestString(inputpointer ) ) ;
@admin@0x3a.com – that code will most likely crash due to lack of null terminator (crash is not guaranteed though)
char input[2];
cin >> input[0];
input[1]=0;
puts( md5.digestString(input) ) ;
can anyone give me a hint as to where i can find a c++ source code for content defined chunking? it could be MD5 or rabin fingerprint
Watch out guys: this implementation does not produce the correct MD5 value on Linux 64-bit (or other LP64 system).
Linux 64-bit uses the LP64 model where an unsigned long is 64-bit, while on Windows (LLP64 system) an unsigned long is still 32-bit.
See this page for more information: http://technet.microsoft.com/en-us/library/bb496995.aspx
To make it work, you need to replace the definition of UINT4 from ‘unsigned long int’ to ‘unsigned int’. That will work on both architectures (Win 32, Win 64, Linux 32, Linux 64) and produce the same results.
Fabrizio (fabriziobertocci-at-gmail.com)
Interesting. Now is that an issue in the MD5 library, see http://stackoverflow.com/questions/697361/md5-hash-calculates-differently-on-server. When I get access to a Linux 64 bit system, I will make the changes and test it, for now LEAVING CODE AS IS (not changed).
its not working for me, getting only 4 character as the result
Works perfectly for me. Thanks for sharing.
D.
Bobobobo! I don’t know who you are and on this big wide web we may never see each other again but for this wonderful gift of a C++ MD5 implementation I *love* you! :-)
My picture is in my avi. I’m Galvatron.
I’m also on http://stackoverflow.com/users/111307/bobobobo
hi guys while running this file i get this error
make: Makefile: No such file or directory
im new to c++, can anyone help me ?
hello
can i use this md5.h in my own project on github?
is it ok?
@troy Yes, you definitely can.
This is an absolute masterpiece of a find. Thank you. It outperformed my CRC fingerprint 7 to 1, saved me so much cycles.
Hello,
I am using the user input version that admin@0x3a.com suggested, but am getting incorrect results.
If I input, say ‘h’, I get an incorrect reslut not ‘2510c39011c5be704182423e3a695e91’ as returned from other md5 algos on the Internet.
The code:
MD5 md5 ;
char input;
cin >> input;
char* inputpointer = &input;
puts( md5.digestString(inputpointer ) ) ;
What is wrong?
Thanks in advance.
I wonder if works correctly with a 15 Gb file ( .iso ), my computer has 1TB HD , 6GB RAM
hello sir.
i am seriously in love with this code thankyou for that!
i have one little problem only the problem K.Chris is having!
“””Hello,
I am using the user input version that admin@0x3a.com suggested, but am getting incorrect results.
If I input, say ‘h’, I get an incorrect reslut not ‘2510c39011c5be704182423e3a695e91′ as returned from other md5 algos on the Internet.
The code:
MD5 md5 ;
char input;
cin >> input;
char* inputpointer = &input;
puts( md5.digestString(inputpointer ) ) ;
What is wrong?
Thanks in advance.”””
please answer it…
its creating a headache
thankyou in advance
Thank You!! Working very well
This is no c++ (puts, string.h…)
For some, puts() and printf() are preferred alternatives to cout, even from C++
This implementation would appear to be flawed.
The following example produces an incorrect (fdf718e277d5169264cf2c6ebdfba32b) hash, should be ‘8cf1a2abe9cf949d737d4aae1dd3b45c’.
char* data = “{\”data\”:{\”code\”:40004,\”message\”:\”The exchange is refusing to process the request because the requested URI could not be found within the exchange.\”,\”status\”:404,\”title\”:\”Not Found\”,\”type\”:\”error\”}}”;
MD5 checksum;
checksum.digestString( data );
We’ve validated this against the following implementations.
http://onlinemd5.com/
https://www.functions-online.com/md5.html
https://defuse.ca/checksums.htm
http://www.opensource.apple.com/source/cups/cups-30/cups/md5.h
The list goes on.
It actually does work, when I run the line:
puts( md5.digestString( “{\”data\”:{\”code\”:40004,\”message\”:\”The exchange is refusing to process the request because the requested URI could not be found within the exchange.\”,\”status\”:404,\”title\”:\”Not Found\”,\”type\”:\”error\”}}” ) ) ;
we get “8cf1a2abe9cf949d737d4aae1dd3b45c”
Thank You!
This code works even in VC6
Only have to comment out 4 lines
//#pragma region
int main()
{
MD5 md5;
printf(“md5 of ‘grape’: %s \n”,md5.digestString(“grape”));
return 0;
}
output:
md5 of ‘grape’: b781cbb29054db12f88f08c6e161c199
How us noobs brake your wonderful code!
This example shows why it sometimes does not work.
LPTSTR MD5FileSum;
LPTSTR MD5FSumWin;
MD5FileSum = md5.digestFile(File1);
MD5FSumWin = md5.digestFile(File3);
printf(“md5FileSum %s \n”,MD5FileSum); //it worked
printf(“md5SumWin %s \n”,MD5FSumWin); //worked again were in business now!
//now.. it didn’t work. It prints the previous computed value, because I’m referencing a pointer not actual string data.
printf(“md5FileSum %s \n”,MD5FileSum);
You have to create a new char string and store the data there, then the code will work as expected.
You’re right that the digest returned is a pointer to the digestChars variable inside the MD5 class. You’ll need to call strdup() to preserve old digest values or store it in an STL string, which will copy it automatically.
@Fabrizio Good catch, friend. You’ve saved me a big headache.
UINT2 is never used
5 Trackbacks/Pingbacks
[…] checksum class: I used the implementation that I found here, I don't know how much we can trust that, but so far it do the trick, (mini note: I have just found […]
[…] contacted me about my MD5 C++ code which is simply the original MD5 functions wrapped in a C++ […]
[…] Do some search in google about the algorithms used in MD5, SHA1, RIPEMD-160, etc. You’ll easily find some implementations. […]
[…] have done some research and i have modified this code, but the problem is the hash algorithm is md5 and i would like it to be sha256 (but i […]
[…] I put up an implementation here. […]