md5sum.c
#include <stdio.h> #include <stdlib.h> #include "md5.h" #pragma warning(disable:4996) #define BUFFER_SIZE 0x200000 void print_digest(const unsigned char* digest); void print_digest(const unsigned char* digest) { int i; ; i < ; i++ ) { printf("%02x", *digest++); } } int main(int argc, char* argv[]) { struct MD5Context md5; unsigned char* buffer; unsigned ]; size_t len; FILE* file; int i; // check the arguments. ) { printf("use this program as:\n md5sum file1 file2 file3...\n"); ); } // Get the memory as the buffer. buffer = (unsigned char*)malloc(BUFFER_SIZE); if ( buffer == NULL ) { printf("Have not enought memory to do this work!\n"); ); } // One by one. ; i < argc; i++ ) { MD5Init(&md5); // open the file. file = fopen(argv[i], "rb"); if ( file == NULL ) { printf("Can't open file: %s\n", argv[i]); continue; } // read the data from the file. , BUFFER_SIZE, file)) > ) { MD5Update(&md5, (const unsigned char*)buffer, (unsigned int)len); } // Finish and show it. MD5Final(digest, &md5); fclose(file); printf("%s: ", argv[i]); print_digest((const unsigned char*)digest); printf("\n"); } // Free the memory. free((void*)buffer); ); }
md5.c
/* * This code implements the MD5 message-digest algorithm. * The algorithm is due to Ron Rivest. This code was * written by Colin Plumb in 1993, no copyright is claimed. * This code is in the public domain; do with it what you wish. * * Equivalent code is available from RSA Data Security, Inc. * This code has been tested against that, and is equivalent, * except that you don't need to include two pages of legalese * with every copy. * * To compute the message digest of a chunk of bytes, declare an * MD5Context structure, pass it to MD5Init, call MD5Update as * needed on buffers full of bytes, and then call MD5Final, which * will fill a supplied 16-byte array with the digest. */ #include <string.h> /* for memcpy() */ #include "md5.h" #ifndef HIGHFIRST #define byteReverse(buf, len) /* Nothing */ #else void byteReverse(unsigned char *buf, unsigned longs); #ifndef ASM_MD5 /* * Note: this code is harmless on little-endian machines. */ void byteReverse(unsigned char *buf, unsigned longs) { unsigned long t; do { t = (unsigned ] << | buf[]) << | ((unsigned) buf[] << | buf[]); *(unsigned long *) buf = t; buf += ; } while (--longs); } #endif #endif /* * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious * initialization constants. */ void MD5Init(struct MD5Context *ctx) { ctx->buf[] = 0x67452301; ctx->buf[] = 0xefcdab89; ctx->buf[] = 0x98badcfe; ctx->buf[] = 0x10325476; ctx->bits[] = ; ctx->bits[] = ; } /* * Update context to reflect the concatenation of another buffer full * of bytes. */ void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) { unsigned long t; //Update bitcount t = ctx->bits[]; ] = t + ((unsigned )) < t) ctx->bits[]++; // Carry from low to high ctx->bits[] += len >> ; t = (t >> ) & 0x3f; // Bytes already in shsInfo->data //Handle any leading odd-sized chunks if (t) { unsigned char *p = (unsigned char *) ctx->in + t; t = - t; if (len < t) { memcpy(p, buf, len); return; } memcpy(p, buf, t); byteReverse(ctx->); MD5Transform(ctx->buf, (unsigned long *) ctx->in); buf += t; len -= t; } // Process data in 64-byte chunks ) { memcpy(ctx->); byteReverse(ctx->); MD5Transform(ctx->buf, (unsigned long *) ctx->in); buf += ; len -= ; } // Handle any remaining bytes of data. memcpy(ctx->in, buf, len); } /* * Final wrapup - pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ ], struct MD5Context *ctx) { unsigned count; unsigned char *p; // Compute number of bytes mod 64 count = (ctx->bits[] >> ) & 0x3F; //Set the first char of padding to 0x80. This is safe since there is // always at least one byte free p = ctx->in + count; *p++ = 0x80; // Bytes of padding needed to make 64 bytes count = - - count; // Pad out to 56 mod 64 ) { // Two lots of padding: Pad the first block to 64 bytes memset(p, , count); byteReverse(ctx->); MD5Transform(ctx->buf, (unsigned long *) ctx->in); // Now fill the next block with 56 bytes memset(ctx->, ); } else { // Pad block to 56 bytes memset(p, , count - ); } byteReverse(ctx->); //Append length in bits and transform ((unsigned ] = ctx->bits[]; ((unsigned ] = ctx->bits[]; MD5Transform(ctx->buf, (unsigned long *) ctx->in); byteReverse((unsigned ); memcpy(digest, ctx->buf, ); memset(ctx, , sizeof(ctx)); // In case it's sensitive } #ifndef ASM_MD5 /* The four core functions - F1 is optimized somewhat */ /* #define F1(x, y, z) (x & y | ~x & z) */ #define F1(x, y, z) (z ^ (x & (y ^ z))) #define F2(x, y, z) F1(z, x, y) #define F3(x, y, z) (x ^ y ^ z) #define F4(x, y, z) (y ^ (x | ~z)) /* This is the central step in the MD5 algorithm. */ #define MD5STEP(f, w, x, y, z, data, s) \ ( w += f(x, y, z) + data, w = w<<s | w>>(-s), w += x ) /* * 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. */ ], unsigned ]) { register unsigned long a, b, c, d; a = buf[]; b = buf[]; c = buf[]; d = buf[]; MD5STEP(F1, a, b, c, d, ] + ); MD5STEP(F1, d, a, b, c, ] + ); MD5STEP(F1, c, d, a, b, ] + ); MD5STEP(F1, b, c, d, a, ] + ); MD5STEP(F1, a, b, c, d, ] + ); MD5STEP(F1, d, a, b, c, ] + ); MD5STEP(F1, c, d, a, b, ] + ); MD5STEP(F1, b, c, d, a, ] + ); MD5STEP(F1, a, b, c, d, ] + ); MD5STEP(F1, d, a, b, c, ] + ); MD5STEP(F1, c, d, a, b, ] + ); MD5STEP(F1, b, c, d, a, ] + ); MD5STEP(F1, a, b, c, d, ] + ); MD5STEP(F1, d, a, b, c, ] + ); MD5STEP(F1, c, d, a, b, ] + ); MD5STEP(F1, b, c, d, a, ] + ); MD5STEP(F2, a, b, c, d, ] + ); MD5STEP(F2, d, a, b, c, ] + ); MD5STEP(F2, c, d, a, b, ] + ); MD5STEP(F2, b, c, d, a, ] + ); MD5STEP(F2, a, b, c, d, ] + ); MD5STEP(F2, d, a, b, c, ] + ); MD5STEP(F2, c, d, a, b, ] + ); MD5STEP(F2, b, c, d, a, ] + ); MD5STEP(F2, a, b, c, d, ] + ); MD5STEP(F2, d, a, b, c, ] + ); MD5STEP(F2, c, d, a, b, ] + ); MD5STEP(F2, b, c, d, a, ] + ); MD5STEP(F2, a, b, c, d, ] + ); MD5STEP(F2, d, a, b, c, ] + ); MD5STEP(F2, c, d, a, b, ] + ); MD5STEP(F2, b, c, d, a, ] + ); MD5STEP(F3, a, b, c, d, ] + ); MD5STEP(F3, d, a, b, c, ] + ); MD5STEP(F3, c, d, a, b, ] + ); MD5STEP(F3, b, c, d, a, ] + ); MD5STEP(F3, a, b, c, d, ] + ); MD5STEP(F3, d, a, b, c, ] + ); MD5STEP(F3, c, d, a, b, ] + ); MD5STEP(F3, b, c, d, a, ] + ); MD5STEP(F3, a, b, c, d, ] + ); MD5STEP(F3, d, a, b, c, ] + ); MD5STEP(F3, c, d, a, b, ] + ); MD5STEP(F3, b, c, d, a, ] + ); MD5STEP(F3, a, b, c, d, ] + ); MD5STEP(F3, d, a, b, c, ] + ); MD5STEP(F3, c, d, a, b, ] + ); MD5STEP(F3, b, c, d, a, ] + ); MD5STEP(F4, a, b, c, d, ] + ); MD5STEP(F4, d, a, b, c, ] + ); MD5STEP(F4, c, d, a, b, ] + ); MD5STEP(F4, b, c, d, a, ] + ); MD5STEP(F4, a, b, c, d, ] + ); MD5STEP(F4, d, a, b, c, ] + ); MD5STEP(F4, c, d, a, b, ] + ); MD5STEP(F4, b, c, d, a, ] + ); MD5STEP(F4, a, b, c, d, ] + ); MD5STEP(F4, d, a, b, c, ] + ); MD5STEP(F4, c, d, a, b, ] + ); MD5STEP(F4, b, c, d, a, ] + ); MD5STEP(F4, a, b, c, d, ] + ); MD5STEP(F4, d, a, b, c, ] + ); MD5STEP(F4, c, d, a, b, ] + ); MD5STEP(F4, b, c, d, a, ] + ); buf[] += a; buf[] += b; buf[] += c; buf[] += d; } #endif
md5.h
#ifndef MD5_H #define MD5_H #ifdef __alpha typedef unsigned int uint32; #else typedef unsigned long uint32; #endif struct MD5Context { uint32 buf[]; uint32 bits[]; unsigned ]; }; void MD5Init(struct MD5Context *context); void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len); ], struct MD5Context *context); ], uint32 ]); /* * This is needed to make RSAREF happy on some MS-DOS compilers. */ typedef struct MD5Context MD5_CTX; #endif /* !MD5_H */