0.9.8.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
md5.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2007-2015 Hypertable, Inc.
3  *
4  * This file is part of Hypertable.
5  *
6  * Hypertable is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 3
9  * of the License, or any later version.
10  *
11  * Hypertable is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  * 02110-1301, USA.
20  */
21 
30 #define SELF_TEST 1
31 #ifndef _CRT_SECURE_NO_DEPRECATE
32 #define _CRT_SECURE_NO_DEPRECATE 1
33 #endif
34 
35 #include <string.h>
36 #include <stdio.h>
37 #include <stdint.h>
38 
39 #include "md5.h"
40 
41 /*
42  * Translation Table as described in RFC 4648
43  */
44 static const char mb64_charset[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
45 
46 /*
47  * 32-bit integer manipulation macros (little endian)
48  */
49 #ifndef GET_UINT32_LE
50 #define GET_UINT32_LE(n,b,i) \
51 { \
52  (n) = ( (unsigned long) (b)[(i) ] ) \
53  | ( (unsigned long) (b)[(i) + 1] << 8 ) \
54  | ( (unsigned long) (b)[(i) + 2] << 16 ) \
55  | ( (unsigned long) (b)[(i) + 3] << 24 ); \
56 }
57 #endif
58 #ifndef PUT_UINT32_LE
59 #define PUT_UINT32_LE(n,b,i) \
60 { \
61  (b)[(i) ] = (unsigned char) ( (n) ); \
62  (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
63  (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
64  (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
65 }
66 #endif
67 
68 /*
69  * MD5 context setup
70  */
71 void md5_starts( md5_context *ctx )
72 {
73  ctx->total[0] = 0;
74  ctx->total[1] = 0;
75 
76  ctx->state[0] = 0x67452301;
77  ctx->state[1] = 0xEFCDAB89;
78  ctx->state[2] = 0x98BADCFE;
79  ctx->state[3] = 0x10325476;
80 }
81 
82 static void md5_process( md5_context *ctx, const unsigned char data[64] )
83 {
84  unsigned long X[16], A, B, C, D;
85 
86  GET_UINT32_LE( X[0], data, 0 );
87  GET_UINT32_LE( X[1], data, 4 );
88  GET_UINT32_LE( X[2], data, 8 );
89  GET_UINT32_LE( X[3], data, 12 );
90  GET_UINT32_LE( X[4], data, 16 );
91  GET_UINT32_LE( X[5], data, 20 );
92  GET_UINT32_LE( X[6], data, 24 );
93  GET_UINT32_LE( X[7], data, 28 );
94  GET_UINT32_LE( X[8], data, 32 );
95  GET_UINT32_LE( X[9], data, 36 );
96  GET_UINT32_LE( X[10], data, 40 );
97  GET_UINT32_LE( X[11], data, 44 );
98  GET_UINT32_LE( X[12], data, 48 );
99  GET_UINT32_LE( X[13], data, 52 );
100  GET_UINT32_LE( X[14], data, 56 );
101  GET_UINT32_LE( X[15], data, 60 );
102 
103 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
104 
105 #define P(a,b,c,d,k,s,t) \
106 { \
107  a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
108 }
109 
110  A = ctx->state[0];
111  B = ctx->state[1];
112  C = ctx->state[2];
113  D = ctx->state[3];
114 
115 #define F(x,y,z) (z ^ (x & (y ^ z)))
116 
117  P( A, B, C, D, 0, 7, 0xD76AA478 );
118  P( D, A, B, C, 1, 12, 0xE8C7B756 );
119  P( C, D, A, B, 2, 17, 0x242070DB );
120  P( B, C, D, A, 3, 22, 0xC1BDCEEE );
121  P( A, B, C, D, 4, 7, 0xF57C0FAF );
122  P( D, A, B, C, 5, 12, 0x4787C62A );
123  P( C, D, A, B, 6, 17, 0xA8304613 );
124  P( B, C, D, A, 7, 22, 0xFD469501 );
125  P( A, B, C, D, 8, 7, 0x698098D8 );
126  P( D, A, B, C, 9, 12, 0x8B44F7AF );
127  P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
128  P( B, C, D, A, 11, 22, 0x895CD7BE );
129  P( A, B, C, D, 12, 7, 0x6B901122 );
130  P( D, A, B, C, 13, 12, 0xFD987193 );
131  P( C, D, A, B, 14, 17, 0xA679438E );
132  P( B, C, D, A, 15, 22, 0x49B40821 );
133 
134 #undef F
135 
136 #define F(x,y,z) (y ^ (z & (x ^ y)))
137 
138  P( A, B, C, D, 1, 5, 0xF61E2562 );
139  P( D, A, B, C, 6, 9, 0xC040B340 );
140  P( C, D, A, B, 11, 14, 0x265E5A51 );
141  P( B, C, D, A, 0, 20, 0xE9B6C7AA );
142  P( A, B, C, D, 5, 5, 0xD62F105D );
143  P( D, A, B, C, 10, 9, 0x02441453 );
144  P( C, D, A, B, 15, 14, 0xD8A1E681 );
145  P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
146  P( A, B, C, D, 9, 5, 0x21E1CDE6 );
147  P( D, A, B, C, 14, 9, 0xC33707D6 );
148  P( C, D, A, B, 3, 14, 0xF4D50D87 );
149  P( B, C, D, A, 8, 20, 0x455A14ED );
150  P( A, B, C, D, 13, 5, 0xA9E3E905 );
151  P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
152  P( C, D, A, B, 7, 14, 0x676F02D9 );
153  P( B, C, D, A, 12, 20, 0x8D2A4C8A );
154 
155 #undef F
156 
157 #define F(x,y,z) (x ^ y ^ z)
158 
159  P( A, B, C, D, 5, 4, 0xFFFA3942 );
160  P( D, A, B, C, 8, 11, 0x8771F681 );
161  P( C, D, A, B, 11, 16, 0x6D9D6122 );
162  P( B, C, D, A, 14, 23, 0xFDE5380C );
163  P( A, B, C, D, 1, 4, 0xA4BEEA44 );
164  P( D, A, B, C, 4, 11, 0x4BDECFA9 );
165  P( C, D, A, B, 7, 16, 0xF6BB4B60 );
166  P( B, C, D, A, 10, 23, 0xBEBFBC70 );
167  P( A, B, C, D, 13, 4, 0x289B7EC6 );
168  P( D, A, B, C, 0, 11, 0xEAA127FA );
169  P( C, D, A, B, 3, 16, 0xD4EF3085 );
170  P( B, C, D, A, 6, 23, 0x04881D05 );
171  P( A, B, C, D, 9, 4, 0xD9D4D039 );
172  P( D, A, B, C, 12, 11, 0xE6DB99E5 );
173  P( C, D, A, B, 15, 16, 0x1FA27CF8 );
174  P( B, C, D, A, 2, 23, 0xC4AC5665 );
175 
176 #undef F
177 
178 #define F(x,y,z) (y ^ (x | ~z))
179 
180  P( A, B, C, D, 0, 6, 0xF4292244 );
181  P( D, A, B, C, 7, 10, 0x432AFF97 );
182  P( C, D, A, B, 14, 15, 0xAB9423A7 );
183  P( B, C, D, A, 5, 21, 0xFC93A039 );
184  P( A, B, C, D, 12, 6, 0x655B59C3 );
185  P( D, A, B, C, 3, 10, 0x8F0CCC92 );
186  P( C, D, A, B, 10, 15, 0xFFEFF47D );
187  P( B, C, D, A, 1, 21, 0x85845DD1 );
188  P( A, B, C, D, 8, 6, 0x6FA87E4F );
189  P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
190  P( C, D, A, B, 6, 15, 0xA3014314 );
191  P( B, C, D, A, 13, 21, 0x4E0811A1 );
192  P( A, B, C, D, 4, 6, 0xF7537E82 );
193  P( D, A, B, C, 11, 10, 0xBD3AF235 );
194  P( C, D, A, B, 2, 15, 0x2AD7D2BB );
195  P( B, C, D, A, 9, 21, 0xEB86D391 );
196 
197 #undef F
198 
199  ctx->state[0] += A;
200  ctx->state[1] += B;
201  ctx->state[2] += C;
202  ctx->state[3] += D;
203 }
204 
205 /*
206  * MD5 process buffer
207  */
208 void md5_update( md5_context *ctx, const unsigned char *input, int ilen )
209 {
210  int fill;
211  unsigned long left;
212 
213  if( ilen <= 0 )
214  return;
215 
216  left = ctx->total[0] & 0x3F;
217  fill = 64 - left;
218 
219  ctx->total[0] += ilen;
220  ctx->total[0] &= 0xFFFFFFFF;
221 
222  if( ctx->total[0] < (unsigned long) ilen )
223  ctx->total[1]++;
224 
225  if( left && ilen >= fill )
226  {
227  memcpy( (void *) (ctx->buffer + left),
228  (void *) input, fill );
229  md5_process( ctx, ctx->buffer );
230  input += fill;
231  ilen -= fill;
232  left = 0;
233  }
234 
235  while( ilen >= 64 )
236  {
237  md5_process( ctx, input );
238  input += 64;
239  ilen -= 64;
240  }
241 
242  if( ilen > 0 )
243  {
244  memcpy( (void *) (ctx->buffer + left),
245  (void *) input, ilen );
246  }
247 }
248 
249 static const unsigned char md5_padding[64] =
250 {
251  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
252  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
253  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
254  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
255 };
256 
257 /*
258  * MD5 final digest
259  */
260 void md5_finish( md5_context *ctx, unsigned char output[16] )
261 {
262  unsigned long last, padn;
263  unsigned long high, low;
264  unsigned char msglen[8];
265 
266  high = ( ctx->total[0] >> 29 )
267  | ( ctx->total[1] << 3 );
268  low = ( ctx->total[0] << 3 );
269 
270  PUT_UINT32_LE( low, msglen, 0 );
271  PUT_UINT32_LE( high, msglen, 4 );
272 
273  last = ctx->total[0] & 0x3F;
274  padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
275 
276  md5_update( ctx, (unsigned char *) md5_padding, padn );
277  md5_update( ctx, msglen, 8 );
278 
279  PUT_UINT32_LE( ctx->state[0], output, 0 );
280  PUT_UINT32_LE( ctx->state[1], output, 4 );
281  PUT_UINT32_LE( ctx->state[2], output, 8 );
282  PUT_UINT32_LE( ctx->state[3], output, 12 );
283 }
284 
285 /*
286  * Output = MD5( file contents )
287  */
288 int md5_file( char *path, unsigned char output[16] )
289 {
290  FILE *f;
291  size_t n;
292  md5_context ctx;
293  unsigned char buf[1024];
294 
295  if( ( f = fopen( path, "rb" ) ) == NULL )
296  return( 1 );
297 
298  md5_starts( &ctx );
299 
300  while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
301  md5_update( &ctx, buf, (int) n );
302 
303  md5_finish( &ctx, output );
304 
305  fclose( f );
306  return( 0 );
307 }
308 
309 /*
310  * Output = MD5( input buffer )
311  */
312 void md5_csum( const unsigned char *input, int ilen,
313  unsigned char output[16] )
314 {
315  md5_context ctx;
316 
317  md5_starts( &ctx );
318  md5_update( &ctx, input, ilen );
319  md5_finish( &ctx, output );
320 }
321 
322 /*
323  * Output = HMAC-MD5( input buffer, hmac key )
324  */
325 void md5_hmac( unsigned char *key, int keylen,
326  const unsigned char *input, int ilen,
327  unsigned char output[16] )
328 {
329  int i;
330  md5_context ctx;
331  unsigned char k_ipad[64];
332  unsigned char k_opad[64];
333  unsigned char tmpbuf[16];
334 
335  memset( k_ipad, 0x36, 64 );
336  memset( k_opad, 0x5C, 64 );
337 
338  for( i = 0; i < keylen; i++ )
339  {
340  if( i >= 64 ) break;
341 
342  k_ipad[i] ^= key[i];
343  k_opad[i] ^= key[i];
344  }
345 
346  md5_starts( &ctx );
347  md5_update( &ctx, k_ipad, 64 );
348  md5_update( &ctx, input, ilen );
349  md5_finish( &ctx, tmpbuf );
350 
351  md5_starts( &ctx );
352  md5_update( &ctx, k_opad, 64 );
353  md5_update( &ctx, tmpbuf, 16 );
354  md5_finish( &ctx, output );
355 
356  memset( k_ipad, 0, 64 );
357  memset( k_opad, 0, 64 );
358  memset( tmpbuf, 0, 16 );
359  memset( &ctx, 0, sizeof( md5_context ) );
360 }
361 
362 static const char _md5_src[] = "_md5_src";
363 
364 static const char hex_digits[] = "0123456789ABCDEF";
365 
366 void md5_hex(const void *input, size_t len, char output[33]) {
367  md5_context ctx;
368  unsigned char digest[16];
369 
370  md5_starts(&ctx);
371  md5_update(&ctx, (const unsigned char *)input, len);
372  md5_finish(&ctx, digest);
373 
374  int index, j=0;
375  for (int i=0; i<16; i++) {
376  index = (digest[i] & 0xF0) >> 4;
377  output[j++] = hex_digits[index];
378  index = digest[i] & 0x0F;
379  output[j++] = hex_digits[index];
380  }
381  output[j] = 0;
382 }
383 
384 void md5_string(const char *input, char output[33]) {
385  md5_hex(input, strlen(input), output);
386 }
387 
388 int64_t md5_hash(const char *input) {
389  md5_context ctx;
390  unsigned char digest[16];
391  int64_t hash;
392 
393  md5_starts(&ctx);
394  md5_update(&ctx, (const unsigned char *)input, strlen(input));
395  md5_finish(&ctx, digest);
396 
397  memcpy(&hash, digest, sizeof(int64_t));
398  return hash;
399 
400 }
401 
402 void digest_to_trunc_modified_base64(const char digest[16], char output[17]) {
403  int digest_pos=0;
404  int output_pos=0;
405 
406  while (digest_pos < 12) {
407  // Convert next 3 bytes of digest into 4 bytes of 6 bit chars
408  output[output_pos] = (digest[digest_pos] & 0xfc) >> 2;
409  output[output_pos+1] = ((digest[digest_pos] & 0x03) << 4) |
410  ((digest[digest_pos+1] & 0xf0) >> 4);
411  output[output_pos+2] = ((digest[digest_pos+1] & 0x0f) << 2) |
412  ((digest[digest_pos+2] & 0xc0) >> 6);
413  output[output_pos+3] = digest[digest_pos+2] & 0x3f;
414 
415  // Convert 6 bit chars to modified base64 char
416  for(int ii=0; ii<4; ++ii)
417  output[output_pos+ii] = mb64_charset[(unsigned)output[output_pos+ii]];
418 
419  output_pos += 4;
420  digest_pos += 3;
421  }
422  output[16]='\0';
423 }
424 
425 void md5_trunc_modified_base64(const char *input, char output[17]) {
426  md5_context ctx;
427  unsigned char digest[16];
428  size_t len = strlen(input);
429 
430  md5_starts(&ctx);
431  md5_update(&ctx, (const unsigned char *)input, len);
432  md5_finish(&ctx, digest);
433  digest_to_trunc_modified_base64((const char *)digest, output);
434 }
435 
436 
437 #ifdef SELF_TEST
438 
439 /*
440  * RFC 1321 test vectors
441  */
442 static const char md5_test_str[7][81] =
443 {
444  { "" },
445  { "a" },
446  { "abc" },
447  { "message digest" },
448  { "abcdefghijklmnopqrstuvwxyz" },
449  { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
450  { "12345678901234567890123456789012345678901234567890123456789012" \
451  "345678901234567890" }
452 };
453 
454 static const unsigned char md5_test_sum[7][16] =
455 {
456  { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
457  0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },
458  { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
459  0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },
460  { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
461  0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },
462  { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
463  0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },
464  { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
465  0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },
466  { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
467  0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },
468  { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
469  0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }
470 };
471 
472 
473 /*
474  * Checkup routine
475  */
476 int md5_self_test( void )
477 {
478  int i;
479  unsigned char md5sum[16];
480 
481  for( i = 0; i < 7; i++ )
482  {
483  printf( " MD5 test #%d: ", i + 1 );
484 
485  md5_csum( (unsigned char *) md5_test_str[i],
486  strlen( md5_test_str[i] ), md5sum );
487 
488  if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 )
489  {
490  printf( "failed\n" );
491  return( 1 );
492  }
493 
494  printf( "passed\n" );
495  }
496 
497  printf( "\n" );
498  return( 0 );
499 }
500 #else
501 int md5_self_test( void )
502 {
503  return( 0 );
504 }
505 #endif
unsigned char buffer[64]
Definition: md5.h:47
void md5_hmac(unsigned char *key, int keylen, const unsigned char *input, int ilen, unsigned char output[16])
Calculates a "Hashed MAC" of an input buffer combined with a secret key.
Definition: md5.cc:325
int64_t md5_hash(const char *input)
Returns a 64-bit hash checksum of a null terminated input buffer.
Definition: md5.cc:388
static const char md5_test_str[7][81]
Definition: md5.cc:442
void digest_to_trunc_modified_base64(const char digest[16], char output[17])
Get the modified base64 encoded string of a 16 byte message digest see http://en.wikipedia.org/wiki/Base64#URL_applications for more information.
Definition: md5.cc:402
void md5_trunc_modified_base64(const char *input, char output[17])
Get the modified base64 encoded string of the first 12 Bytes of the 16 Byte MD5 code of a null termin...
Definition: md5.cc:425
void md5_update(md5_context *ctx, const unsigned char *input, int ilen)
Adds data to the MD5 process buffer.
Definition: md5.cc:208
void md5_starts(md5_context *ctx)
Initialize and setup a MD5 context structure.
Definition: md5.cc:71
static const unsigned char md5_padding[64]
Definition: md5.cc:249
void md5_csum(const unsigned char *input, int ilen, unsigned char output[16])
Convenience function to calculate the MD5 sum of an input buffer.
Definition: md5.cc:312
static void md5_process(md5_context *ctx, const unsigned char data[64])
Definition: md5.cc:82
unsigned long state[4]
Definition: md5.h:46
void md5_string(const char *input, char output[33])
Calculates the hex string of MD5 of null terminated input.
Definition: md5.cc:384
static const char hex_digits[]
Definition: md5.cc:364
MD5 context structure; this structure is used to store the internal state of the md5 algorithm...
Definition: md5.h:44
static const unsigned char md5_test_sum[7][16]
Definition: md5.cc:454
#define P(a, b, c, d, k, s, t)
void md5_finish(md5_context *ctx, unsigned char output[16])
Retrieve the final MD5 digest.
Definition: md5.cc:260
int md5_self_test(void)
Runs a self test.
Definition: md5.cc:476
#define GET_UINT32_LE(n, b, i)
Definition: md5.cc:50
void md5_hex(const void *input, size_t len, char output[33])
Convenience function to calculate the MD5 sum of an input buffer; returns string with the MD5 encoded...
Definition: md5.cc:366
#define PUT_UINT32_LE(n, b, i)
Definition: md5.cc:59
int md5_file(char *path, unsigned char output[16])
Definition: md5.cc:288
static const char _md5_src[]
Definition: md5.cc:362
md5 digest routines.
static const char mb64_charset[]
Definition: md5.cc:44
unsigned long total[2]
Definition: md5.h:45