home   articles   tags   browse code   

C++ md5 function


 

I found this on the web and confirmed it was correctly mirroring the md5 result calculated by php md5.

main.cpp
#include <iostream>
#include "md5.h"

using namespace std;

int main(int argc, char *argv[])
{
    cout << "md5 of 'grape': " << md5("grape")<<endl;
    return 0;
}


output:
md5 of 'grape': b781cbb29054db12f88f08c6e161c199

Note: <?php echo "md5 of 'grape': ".md5('grape'); ?> in php produces the same output as above.

md5.h
/* MD5
 converted to C++ class by Frank Thilo (thilo@unix-ag.org)
 for bzflag (http://www.bzflag.org)

   based on:

   md5.h and md5.c
   reference implementation of RFC 1321

   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.

*/


#ifndef BZF_MD5_H
#define BZF_MD5_H

#include <string>
#include <iostream>


// a small class for calculating MD5 hashes of strings or byte arrays
// it is not meant to be fast or secure
//
// usage: 1) feed it blocks of uchars with update()
//      2) finalize()
//      3) get hexdigest() string
//      or
//      MD5(std::string).hexdigest()
//
// assumes that char is 8 bit and int is 32 bit
class MD5
{
public:
  typedef unsigned int size_type; // must be 32bit

  MD5();
  MD5(const std::string& text);
  void update(const unsigned char *buf, size_type length);
  void update(const char *buf, size_type length);
  MD5& finalize();
  std::string hexdigest() const;
  friend std::ostream& operator<<(std::ostream&, MD5 md5);

private:
  void init();
  typedef unsigned char uint1; //  8bit
  typedef unsigned int uint4;  // 32bit
  enum {blocksize = 64}; // VC6 won't eat a const static int here

  void transform(const uint1 block[blocksize]);
  static void decode(uint4 output[], const uint1 input[], size_type len);
  static void encode(uint1 output[], const uint4 input[], size_type len);

  bool finalized;
  uint1 buffer[blocksize]; // bytes that didn't fit in last 64 byte chunk
  uint4 count[2];   // 64bit counter for number of bits (lo, hi)
  uint4 state[4];   // digest so far
  uint1 digest[16]; // the result

  // low level logic operations
  static inline uint4 F(uint4 x, uint4 y, uint4 z);
  static inline uint4 G(uint4 x, uint4 y, uint4 z);
  static inline uint4 H(uint4 x, uint4 y, uint4 z);
  static inline uint4 I(uint4 x, uint4 y, uint4 z);
  static inline uint4 rotate_left(uint4 x, int n);
  static inline void FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
  static inline void GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
  static inline void HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
  static inline void II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
};

std::string md5(const std::string str);

#endif


md5.cpp
/* MD5
 converted to C++ class by Frank Thilo (thilo@unix-ag.org)
 for bzflag (http://www.bzflag.org)

   based on:

   md5.h and md5.c
   reference implemantion of RFC 1321

   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.

*/


/* interface header */
#include "md5.h"

/* system implementation headers */
#include <stdio.h>


// 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

///////////////////////////////////////////////

// F, G, H and I are basic MD5 functions.
inline MD5::uint4 MD5::F(uint4 x, uint4 y, uint4 z) {
  return x&y | ~x&z;
}

inline MD5::uint4 MD5::G(uint4 x, uint4 y, uint4 z) {
  return x&z | y&~z;
}

inline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z) {
  return x^y^z;
}

inline MD5::uint4 MD5::I(uint4 x, uint4 y, uint4 z) {
  return y ^ (x | ~z);
}

// rotate_left rotates x left n bits.
inline MD5::uint4 MD5::rotate_left(uint4 x, int n) {
  return (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.
inline void MD5::FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
  a = rotate_left(a+ F(b,c,d) + x + ac, s) + b;
}

inline void MD5::GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
  a = rotate_left(a + G(b,c,d) + x + ac, s) + b;
}

inline void MD5::HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
  a = rotate_left(a + H(b,c,d) + x + ac, s) + b;
}

inline void MD5::II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
  a = rotate_left(a + I(b,c,d) + x + ac, s) + b;
}

//////////////////////////////////////////////

// default ctor, just initailize
MD5::MD5()
{
  init();
}

//////////////////////////////////////////////

// nifty shortcut ctor, compute MD5 for string and finalize it right away
MD5::MD5(const std::string &text)
{
  init();
  update(text.c_str(), text.length());
  finalize();
}

//////////////////////////////

void MD5::init()
{
  finalized=false;

  count[0] = 0;
  count[1] = 0;

  // load magic initialization constants.
  state[0] = 0x67452301;
  state[1] = 0xefcdab89;
  state[2] = 0x98badcfe;
  state[3] = 0x10325476;
}

//////////////////////////////

// decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4.
void MD5::decode(uint4 output[], const uint1 input[], size_type len)
{
  for (unsigned int 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);
}

//////////////////////////////

// encodes input (uint4) into output (unsigned char). Assumes len is
// a multiple of 4.
void MD5::encode(uint1 output[], const uint4 input[], size_type len)
{
  for (size_type i = 0, j = 0; j < len; i++, j += 4) {
    output[j] = input[i] & 0xff;
    output[j+1] = (input[i] >> 8) & 0xff;
    output[j+2] = (input[i] >> 16) & 0xff;
    output[j+3] = (input[i] >> 24) & 0xff;
  }
}

//////////////////////////////

// apply MD5 algo on a block
void MD5::transform(const uint1 block[blocksize])
{
  uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
  decode (x, block, blocksize);

  /* 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(x, 0, sizeof x);
}

//////////////////////////////

// MD5 block update operation. Continues an MD5 message-digest
// operation, processing another message block
void MD5::update(const unsigned char input[], size_type length)
{
  // compute number of bytes mod 64
  size_type index = count[0] / 8 % blocksize;

  // Update number of bits
  if ((count[0] += (length << 3)) < (length << 3))
    count[1]++;
  count[1] += (length >> 29);

  // number of bytes we need to fill in buffer
  size_type firstpart = 64 - index;

  size_type i;

  // transform as many times as possible.
  if (length >= firstpart)
  {
    // fill buffer first, transform
    memcpy(&buffer[index], input, firstpart);
    transform(buffer);

    // transform chunks of blocksize (64 bytes)
    for (i = firstpart; i + blocksize <= length; i += blocksize)
      transform(&input[i]);

    index = 0;
  }
  else
    i = 0;

  // buffer remaining input
  memcpy(&buffer[index], &input[i], length-i);
}

//////////////////////////////

// for convenience provide a verson with signed char
void MD5::update(const char input[], size_type length)
{
  update((const unsigned char*)input, length);
}

//////////////////////////////

// MD5 finalization. Ends an MD5 message-digest operation, writing the
// the message digest and zeroizing the context.
MD5& MD5::finalize()
{
  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
  };

  if (!finalized) {
    // Save number of bits
    unsigned char bits[8];
    encode(bits, count, 8);

    // pad out to 56 mod 64.
    size_type index = count[0] / 8 % 64;
    size_type padLen = (index < 56) ? (56 - index) : (120 - index);
    update(padding, padLen);

    // Append length (before padding)
    update(bits, 8);

    // Store state in digest
    encode(digest, state, 16);

    // Zeroize sensitive information.
    memset(buffer, 0, sizeof buffer);
    memset(count, 0, sizeof count);

    finalized=true;
  }

  return *this;
}

//////////////////////////////

// return hex representation of digest as string
std::string MD5::hexdigest() const
{
  if (!finalized)
    return "";

  char buf[33];
  for (int i=0; i<16; i++)
    sprintf(buf+i*2, "%02x", digest[i]);
  buf[32]=0;

  return std::string(buf);
}

//////////////////////////////

std::ostream& operator<<(std::ostream& out, MD5 md5)
{
  return out << md5.hexdigest();
}

//////////////////////////////

std::string md5(const std::string str)
{
    MD5 md5 = MD5(str);

    return md5.hexdigest();
}
 

Tags: c++
 
Anon on Aug 9th, 2009 7:06 pm said:
I think you need to be a little more clear how you use this since your "example" is not how it works.
 

Max on Sep 16th, 2009 3:01 pm said:
This works perfectly. Thanks alot for this. It's also about 10 (!!!) times faster than windows built in wincrypt.h libraries.
 

Anon on Oct 13th, 2009 2:34 pm said:
I would like to thank you from this code. Afaik, i got it work 100% on c++ builder 2007. So far this is the only code i found effective for my problem, which even google werent able to sort out. Thank you!
 

Mike on Oct 28th, 2009 1:23 pm said:
Great work! Thanks for posting it. It worked from C++ builder without any modifications. String hashResult=md5(stringToHash.c_str()).c_str();
 

Anon on Nov 22nd, 2009 5:23 pm said:
thank you very much.
 

Cris on Dec 1st, 2009 11:34 am said:
im getting this error main.cpp|299|undefined reference to `md5(std::string)' cout
 

Michael on Dec 2nd, 2009 4:57 pm said:
B E A utiful... thanks for that, saved me hours... Almost thaught it wasn't working but i hadn't included my salt prefixes. thanks and i'm using code::blocks and have tested with both g++ and mingw32. thanks again. To cris, you are obviously not including the md5.cpp program in your compile, the easyest way you can ensure it is included in any compiler is just to add a line; #include md5.cpp (works same as header files, just appends the code to the end).
 

abdurrm on Dec 18th, 2009 5:16 pm said:
thanks its working, but why I can't use #include "md5.h" with error message same like Cris?
 

tesla on Jan 9th, 2010 9:04 pm said:
Thanks for this one, great work!
 

Arne on Feb 10th, 2010 2:40 pm said:
I like it this far! Works just fine!, but could anyone tell me how to use it in order to get the md5 of a (129MB...slow?) file? Have a nice day!
 

MeMo on Feb 14th, 2010 6:11 pm said:
how can i run it!!!??? and could it run using borland C++ 5.02??? please i want help
 

nbeagle on May 5th, 2010 6:02 am said:
I needed to include for compiler to find memset (using g++ on ubuntu).
 

nbeagle on May 5th, 2010 6:03 am said:
I needed to include string.h for the compiler to find memset
 

Simon Rodan on Jun 11th, 2010 11:55 pm said:
#include for memset
 

Simon Rodan on Jun 11th, 2010 11:57 pm said:
Previous comment should read "include " (the contents of the angle brackets [memory.h] were removed by the html parser) - hope this works better.
 

Simon Rodan on Jun 11th, 2010 11:59 pm said:
Last try: #include for memset
 

Eric on Jun 27th, 2010 12:41 pm said:
To use this in VC++, I need to comment/uncomment include "md5.cpp" every time I compile, kind annoying..
 

panthere on Jul 20th, 2010 5:23 pm said:
Hello this code is interesting in May does not compile with g++ main.cpp:11: warning: unused parameter ‘argc’ main.cpp:11: warning: unused parameter ‘argv’ /tmp/cczvyQno.o: In function `main': main.cpp:(.text+0x46): undefined reference to `md5(std::basic_string)' collect2: ld returned 1 exit status command: g++ main.cpp -Wall -Wextra -ansi -pedantic -lm -o main
 

panthere on Jul 22nd, 2010 6:44 pm said:
solver : add #include "md5.cpp" in main.cpp and add: #include in md5.cpp
 

vegetoine on Aug 8th, 2010 4:54 pm said:
Beautiful !! just add #include "md5.cpp" as said above, and if you have errors related to memset or memcpy juste add : #include to md5.cpp
 

vegetoine on Aug 8th, 2010 4:56 pm said:
Oh, my comment was fucked up, well just follow this : http://sumoudou.org/%E7%9B%B8%E6%92%B2%E5%A4%96%EF%BC%9AFixing%20the%20memset%20was%20not%20declared%20in%20this%20scope%20error.html
 

dirk on Aug 17th, 2010 1:54 pm said:
Can this algorithm be applied to the WebSocket handshake? The webSocket handshake response requires a 128-bit (16 byte) response. This algorithm, as it stands returns a 32 byte chunk of data.
 

Phionperv on Sep 14th, 2010 6:22 pm said:
I got this message after compiling, "MD5.h(61,22):'ostream' is not a member of 'std'. What happened exactly? 0_o
 

littlejohn on Sep 30th, 2010 11:53 pm said:
I have tested this code on windows, in borland. It seems to work fine. However, I checked MD5 values with another tool (DiamondCS MD5 Utility) and it presented differences for large files (for me, >500MB). Does anyone can confirm this? If it has a bug, can anyone help to fix? thanx
 

littlejohn on Oct 19th, 2010 9:54 pm said:
Please!
 

2 on Nov 11th, 2010 4:14 am said:
littlejohn, the problem is not the code here. Its the way you implemented feed of file data to md5 input.
 

littlejohn on Nov 13th, 2010 9:36 pm said:
Ok. I think the code is correct as it works for crc32 (checked against other sw) and correct also for MD5 for files up to 100~200 MB. In October, I have also found some comments talking that Diamond presented some errors. I will check more and if I find something useful I post here. Thanx for your contribution.
 

Shacki on Nov 19th, 2010 4:28 am said:
I search a md5 function for unicode.
 

shiny666 on Dec 12th, 2010 7:39 pm said:
needed to #include in md5.cpp to get it functional here. also implemented with #include "md5.cpp" in my file, obviously. --shiny
 

bobo on Dec 17th, 2010 10:49 am said:
I confirm, DiamondCS MD5 Utility also generates incorrect checksums for me on large files (~500mb). Shame, cause I kinda liked it's simple UI
 

MASTER on Jan 16th, 2011 1:05 am said:
Thanks buddy, I liked your code very much, To those who are getting errors add both files (md5.h and md5.cpp) into your project then compile problems arisis when you only try to compile the main.cpp file without adding above mentioned two files in your project. Thanks again for this wonderful code.
 

Tommy on Jan 29th, 2011 6:25 pm said:
Thank you!! This code took less than 2 minutes to throw into my project and start using. Exactly what I needed...it is amazing.
 

Fedot on Feb 11th, 2011 7:20 am said:
Beautifull!
 

aravi on Feb 14th, 2011 10:23 am said:
hi need a help, code works perfectly,my project involves this code and i would be thankful if anyone explain me "Update" function in it. Please someone please help me, i am really desperate i tried a lot but i couldnt understand it. Here is my email id aravindan333@gmail.com
 

narendra on Feb 17th, 2011 12:50 am said:
hiiii thanx a lot...ur programme is of no use to me....i was scolded by mam...for not running..
 

Colagusano on Feb 24th, 2011 1:18 pm said:
Hi all! I have this error when I compile this code on g++ (ubuntu). HELP please. /tmp/ccXF9bUM.o: In function `main': main.cpp:(.text+0x46): undefined reference to `md5(std::basic_string)' collect2: ld returned 1 exit status
 

chubakueno on May 12th, 2011 6:36 pm said:
How can I get the result into a char?
 

SIFE on May 13th, 2011 4:04 am said:
Why MySQL MD5 return a different hash from this function?
 

Antuan on Jul 1st, 2011 2:38 am said:
GGGGGrreat ! thank u very much : D
 

bahaba on Aug 10th, 2011 2:30 pm said:
Terrific! Only needed to add an extern for md5() and add an include for string.h (for memset, memcpy)... using MINGW g++ compiler on Windows. My test returned the same hash as PHP md5().
 

Aaron on Aug 26th, 2011 9:55 am said:
This is amazing! Thank you! Most useful function in the world :)
 

Billiam on Oct 3rd, 2011 8:10 pm said:
I got this working, however the file hashes return different than the other md5 file hashing programs. Text hashes return correctly though...
 

LOX on Dec 19th, 2011 10:43 pm said:
This program is suck! Get your dick and pick in wall!
 



 

 



Related Articles
 


home  |  privacy policy  |  terms of use  |  contact  


©2012, Zedwood.com

zedwood.com is a participant in the Amazon Services LLC Associates Program, an affiliate advertising program designed to provide a means for sites to earn advertising fees by advertising and linking to amazon.com