3

I want to write a program to hash some data and preferably i would like it to use sha1 or MD5 any of those. I don't know the main logic behind it. I also wanted to know what ways i can take to do it in C.

6
  • 5
    "Encrypt" using MD5 or SHA1? Those are both hashes. Do you want to be able to reverse the process? Commented Mar 17, 2012 at 17:19
  • 2
    MD5 and SHA1 are not encryption algorithms, they are hashing algorithms. A simple wikipedia search would have given you that information. As for the C libraries - are you trying to do this as an exercise or are you open to using an existing library? Commented Mar 17, 2012 at 17:23
  • 1
    Just Google it and try to implement the algorithm. If you have any issue when implementing it, we will help you. Commented Mar 17, 2012 at 17:24
  • as @mattjgalloway said those are hashes not encryption. You should look for AES,DSA,RSA etc. encryptions. Commented Mar 17, 2012 at 17:28
  • i just want to do hashing in C and you can consider it that i am doing like an exercise, for my knowledge and as both are similar it doesn't matter for me that which i choose. I DON'T WANT TO USE ANY LIBRARY FUNCTIONS OR SO. I WANT TO DO IT ALL BY MYSELF Commented Mar 18, 2012 at 5:47

2 Answers 2

6

Use a libray like this (SHA1, SHA256, SHA384, SHA512, MD5, Base64) or, just for MD5, this code

MD5

MD5.H

/* $Id: md5.h,v 1.3 2006-01-02 18:16:26 quentin Exp $ */ /* * Implementation of the md5 algorithm described in RFC1321 * Copyright (C) 2005 Quentin Carbonneaux <[email protected]> * * This file is part of md5sum. * * md5sum is a free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Softawre Foundation; either version 2 of the License, or * (at your option) any later version. * * md5sum is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should hav received a copy of the GNU General Public License * along with md5sum; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef MD5_H #define MD5_H #include <assert.h> #include <stdlib.h> /* WARNING : * This implementation is using 32 bits long values for sizes */ typedef unsigned int md5_size; /* MD5 context */ struct md5_ctx { struct { unsigned int A, B, C, D; /* registers */ } regs; unsigned char *buf; md5_size size; md5_size bits; }; /* Size of the MD5 buffer */ #define MD5_BUFFER 1024 /* Basic md5 functions */ #define F(x,y,z) ((x & y) | (~x & z)) #define G(x,y,z) ((x & z) | (~z & y)) #define H(x,y,z) (x ^ y ^ z) #define I(x,y,z) (y ^ (x | ~z)) /* Rotate left 32 bits values (words) */ #define ROTATE_LEFT(w,s) ((w << s) | ((w & 0xFFFFFFFF) >> (32 - s))) #define FF(a,b,c,d,x,s,t) (a = b + ROTATE_LEFT((a + F(b,c,d) + x + t), s)) #define GG(a,b,c,d,x,s,t) (a = b + ROTATE_LEFT((a + G(b,c,d) + x + t), s)) #define HH(a,b,c,d,x,s,t) (a = b + ROTATE_LEFT((a + H(b,c,d) + x + t), s)) #define II(a,b,c,d,x,s,t) (a = b + ROTATE_LEFT((a + I(b,c,d) + x + t), s)) unsigned char *md5 (unsigned char *, md5_size, unsigned char *); void md5_init (struct md5_ctx *); void md5_update (struct md5_ctx *context); void md5_final (unsigned char *digest, struct md5_ctx *context); #endif /* MD5_H */ 

MD5.c

/* $Id: md5.c,v 1.3 2006-05-01 16:57:31 quentin Exp $ */ /* * Implementation of the md5 algorithm as described in RFC1321 * Copyright (C) 2005 Quentin Carbonneaux <[email protected]> * * This file is part of md5sum. * * md5sum is a free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Softawre Foundation; either version 2 of the License, or * (at your option) any later version. * * md5sum is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should hav received a copy of the GNU General Public License * along with md5sum; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "md5.h" #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 #define memcopy(a,b,c) md5_memcopy ((a), (b), (c)) #define memset(a,b,c) md5_memset ((a), (b), (c)) #define GET_UINT32(a,b,i) \ { \ (a) = ( (unsigned int) (b)[(i) ] ) \ | ( (unsigned int) (b)[(i)+1] << 8 ) \ | ( (unsigned int) (b)[(i)+2] << 16) \ | ( (unsigned int) (b)[(i)+3] << 24); \ } /* local functions */ static void md5_memcopy (unsigned char *, unsigned char *, const unsigned int); static void md5_memset (unsigned char *, const unsigned char, const unsigned int); static void md5_addsize (unsigned char *, md5_size , md5_size); static void md5_encode (unsigned char *, struct md5_ctx *); static unsigned char MD5_PADDING [64] = { /* 512 Bits */ 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 }; /* * An easy way to do the md5 sum of a short memory space */ unsigned char *md5 (unsigned char *M, md5_size len, unsigned char *_digest) { int buflen = (len > MD5_BUFFER) ? MD5_BUFFER: len; struct md5_ctx *context; context = malloc (sizeof (struct md5_ctx)); context->buf = malloc (buflen); context->size = 0; context->bits = 0; /* Init registries */ context->regs.A = 0x67452301; context->regs.B = 0xefcdab89; context->regs.C = 0x98badcfe; context->regs.D = 0x10325476; do { memcopy (context->buf + context->size, M + context->bits, buflen - context->size); context->size += buflen - context->size; md5_update (context); } while (len - context->bits > 64); md5_final (_digest, context); free (context->buf); free (context); return _digest; } void md5_init (struct md5_ctx *context) { context->buf = malloc (MD5_BUFFER); memset (context->buf, '\0', MD5_BUFFER); context->size = 0; context->bits = 0; /* Init registries */ context->regs.A = 0x67452301; context->regs.B = 0xefcdab89; context->regs.C = 0x98badcfe; context->regs.D = 0x10325476; } /* md5_size is bytes while the size at the end of the message is in bits ... */ static void md5_addsize (unsigned char *M, md5_size index, md5_size oldlen) { assert (((index * 8) % 512) == 448); /* If padding is not done then exit */ M[index++] = (unsigned char) ((oldlen << 3) & 0xFF); M[index++] = (unsigned char) ((oldlen >> 5) & 0xFF); M[index++] = (unsigned char) ((oldlen >> 13) & 0xFF); M[index++] = (unsigned char) ((oldlen >> 21) & 0xFF); /* Fill with 0 because md5_size is 32 bits long */ M[index++] = 0; M[index++] = 0; M[index++] = 0; M[index++] = 0; } /* * Update a context by concatenating a new block */ void md5_update (struct md5_ctx *context) { unsigned char buffer [64]; /* 512 bits */ int i; for (i = 0; context->size - i > 63; i += 64) { memcopy (buffer, context->buf + i, 64); md5_encode (buffer, context); context->bits += 64; } memcopy (buffer, context->buf + i, context->size - i); memcopy (context->buf, buffer, context->size - i); context->size -= i; } void md5_final (unsigned char *digest, struct md5_ctx *context) { unsigned char buffer [64]; /* 512 bits */ int i; assert (context->size < 64); if (context->size + 1 > 56) { /* We have to create another block */ memcopy (buffer, context->buf, context->size); memcopy (buffer + context->size, MD5_PADDING, 64 - context->size); md5_encode (buffer, context); context->bits += context->size; context->size = 0; /* Proceed final block */ memset (buffer, '\0', 56); /*memcopy (buffer, MD5_PADDING + 1, 56);*/ md5_addsize (buffer, 56, context->bits); md5_encode (buffer, context); } else { memcopy (buffer, context->buf, context->size); context->bits += context->size; memcopy (buffer + context->size, MD5_PADDING, 56 - context->size); md5_addsize (buffer, 56, context->bits); md5_encode (buffer, context); } /* update digest */ for (i = 0; i < 4; i++) digest [i] = (unsigned char) ((context->regs.A >> (i*8)) & 0xFF); for (; i < 8; i++) digest [i] = (unsigned char) ((context->regs.B >> ((i-4)*8)) & 0xFF); for (; i < 12; i++) digest [i] = (unsigned char) ((context->regs.C >> ((i-8)*8)) & 0xFF); for (; i < 16; i++) digest [i] = (unsigned char) ((context->regs.D >> ((i-12)*8)) & 0xFF); } static void md5_encode (unsigned char *buffer, struct md5_ctx *context) { unsigned int a = context->regs.A, b = context->regs.B, c = context->regs.C, d = context->regs.D; unsigned int x[16]; GET_UINT32 (x[ 0],buffer, 0); GET_UINT32 (x[ 1],buffer, 4); GET_UINT32 (x[ 2],buffer, 8); GET_UINT32 (x[ 3],buffer,12); GET_UINT32 (x[ 4],buffer,16); GET_UINT32 (x[ 5],buffer,20); GET_UINT32 (x[ 6],buffer,24); GET_UINT32 (x[ 7],buffer,28); GET_UINT32 (x[ 8],buffer,32); GET_UINT32 (x[ 9],buffer,36); GET_UINT32 (x[10],buffer,40); GET_UINT32 (x[11],buffer,44); GET_UINT32 (x[12],buffer,48); GET_UINT32 (x[13],buffer,52); GET_UINT32 (x[14],buffer,56); GET_UINT32 (x[15],buffer,60); /* 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 */ context->regs.A += a; context->regs.B += b; context->regs.C += c; context->regs.D += d; } /* OBSOLETE */ static void md5_memcopy (unsigned char *dest, unsigned char *src, unsigned int count) { unsigned int i; for (i = 0; i < count; i++) { dest [i] = src [i]; } } static void md5_memset (unsigned char *p, const unsigned char c, const unsigned int count) { unsigned int i; for (i = 0; i < count; i++) { p [i] = c; } } 

Example

const char *md5sum(const char *chaine, size_t len = 0) { struct md5_ctx ctx; unsigned char digest(16); md5_init(&ctx); ctx.size = len?len:strlen(chaine); strcpy(ctx.buf, chaine); md5_update(&ctx); md5_final(digest, &ctx); return digest; } 
Sign up to request clarification or add additional context in comments.

1 Comment

Your code seems wrong and prone to buffer overflow vulnerability. strcpy(ctx.buf, chaine); -> this line will copy a string of variable lenght controlled by the user into a malloced string of 1024 bytes. Using a safe function, for example strndup(ctx.buf, chaine, strlen(chaine)), can avoid this problem.
5

If you want to learn, I think the NIST specification FIPS 180-4 is an excellent document from which you can implement any of the SHA series including SHA-1.

For MD5, RFC 1321 contains a C implementation in an appendix. Also, read the errata for some bug fixes.

Here is some of the MD5 code from RFC 1321. A few changes were made to simplify it for modern C and to incorporate an important observation from the errata, and the main program has been simplified to only contain the code that runs the test suite.

First, the header file md5.h:

#include <stdint.h> /* POINTER defines a generic pointer type */ typedef unsigned char *POINTER; /* UINT2 defines a two byte word */ typedef uint16_t UINT2; /* UINT4 defines a four byte word */ typedef uint32_t UINT4; /* MD5 context. */ typedef struct { UINT4 state[4]; /* state (ABCD) */ UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } MD5_CTX; void MD5Init(MD5_CTX *); void MD5Update(MD5_CTX *, unsigned char *, unsigned int); void MD5Final(unsigned char[16], MD5_CTX *); 

Next, the MD5 library md5.c:

/* 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. */ #include "md5.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 static void MD5Transform(UINT4[4], unsigned char[64]); static void Encode(unsigned char *, UINT4 *, unsigned int); static void Decode(UINT4 *, unsigned char *, unsigned int); static void MD5_memcpy(POINTER, POINTER, unsigned int); static void MD5_memset(POINTER, int, unsigned int); 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); \ } /* MD5 initialization. Begins an MD5 operation, writing a new context. */ void MD5Init(MD5_CTX *context) { 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 MD5Update(MD5_CTX *context, unsigned char *input, unsigned int inputLen) { 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) { MD5_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 */ MD5_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. */ void MD5Final(unsigned char digest[16], MD5_CTX *context) /* context */ { 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); MD5Update(context, PADDING, padLen); /* Append length (before padding) */ MD5Update(context, bits, 8); /* Store state in digest */ Encode(digest, context->state, 16); /* Zeroize sensitive information. */ MD5_memset((POINTER)context, 0, sizeof(*context)); } /* 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. */ MD5_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); } /* Note: Replace "for loop" with standard memcpy if possible. */ static void MD5_memcpy(POINTER output, POINTER input, unsigned int len) { unsigned int i; for (i = 0; i < len; i++) output[i] = input[i]; } /* Note: Replace "for loop" with standard memset if possible. */ static void MD5_memset(POINTER output, int value, unsigned int len) { unsigned int i; for (i = 0; i < len; i++) ((char *)output)[i] = (char)value; } 

And finally, the main program main.c that runs the test suite:

#include <stdio.h> #include <time.h> #include <string.h> #include "md5.h" static void MD5String (char *); static void MD5TestSuite (void); static void MD5Print (unsigned char [16]); int main(int argc, char *argv[]) { MD5TestSuite(); return 0; } /* Digests a reference suite of strings and prints the results. */ static void MD5TestSuite () { printf ("MD5 test suite:\n"); MD5String(""); MD5String("a"); MD5String("abc"); MD5String("message digest"); MD5String("abcdefghijklmnopqrstuvwxyz"); MD5String("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); MD5String("12345678901234567890123456789012345678901234567890123456789012345678901234567890"); } /* Digests a string and prints the result. */ static void MD5String (char *string) { MD5_CTX context; unsigned char digest[16]; unsigned int len = strlen (string); MD5Init (&context); MD5Update (&context, (unsigned char *)string, len); MD5Final (digest, &context); printf ("MD5(\"%s\") = ", string); MD5Print (digest); printf ("\n"); } /* Prints a message digest in hexadecimal. */ static void MD5Print(unsigned char digest[16]) { unsigned int i; for (i = 0; i < 16; i++) { printf("%02x", digest[i]); } } 

Note that RFC 1321 was published in 1992, so this code is very old.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.