~fractalcat/gearmand/docfixes

« back to all changes in this revision

Viewing changes to libhashkit/md5.cc

  • Committer: Brian Aker
  • Date: 2012-12-13 11:44:26 UTC
  • mto: (621.4.66 workspace)
  • mto: This revision was merged to the branch mainline in revision 676.
  • Revision ID: brian@tangent.org-20121213114426-lnrt6aysy7lqc01h
Adding support for deriving the unique value based on the data that is supplied by the client.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
2
 * 
 
3
 *  HashKit library
 
4
 *
 
5
 *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
 
6
 *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
 
7
 *
 
8
 *  Redistribution and use in source and binary forms, with or without
 
9
 *  modification, are permitted provided that the following conditions are
 
10
 *  met:
 
11
 *
 
12
 *      * Redistributions of source code must retain the above copyright
 
13
 *  notice, this list of conditions and the following disclaimer.
 
14
 *
 
15
 *      * Redistributions in binary form must reproduce the above
 
16
 *  copyright notice, this list of conditions and the following disclaimer
 
17
 *  in the documentation and/or other materials provided with the
 
18
 *  distribution.
 
19
 *
 
20
 *      * The names of its contributors may not be used to endorse or
 
21
 *  promote products derived from this software without specific prior
 
22
 *  written permission.
 
23
 *
 
24
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
25
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
26
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
27
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 
28
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
29
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
30
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
31
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
32
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
33
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
34
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
35
 *
 
36
 */
 
37
 
 
38
/*
 
39
  This Library has been modified from its original form by
 
40
  Brian Aker (brian@tangent.org)
 
41
 
 
42
  See below for original Copyright.
 
43
*/
 
44
/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
 
45
 */
 
46
 
 
47
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
 
48
rights reserved.
 
49
 
 
50
License to copy and use this software is granted provided that it
 
51
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
 
52
Algorithm" in all material mentioning or referencing this software
 
53
or this function.
 
54
 
 
55
License is also granted to make and use derivative works provided
 
56
that such works are identified as "derived from the RSA Data
 
57
Security, Inc. MD5 Message-Digest Algorithm" in all material
 
58
mentioning or referencing the derived work.
 
59
 
 
60
RSA Data Security, Inc. makes no representations concerning either
 
61
the merchantability of this software or the suitability of this
 
62
software for any particular purpose. It is provided "as is"
 
63
without express or implied warranty of any kind.
 
64
 
 
65
These notices must be retained in any copies of any part of this
 
66
documentation and/or software.
 
67
*/
 
68
 
 
69
#include <libhashkit/common.h>
 
70
 
 
71
#include <string.h>
 
72
#include <sys/types.h>
 
73
 
 
74
/* POINTER defines a generic pointer type */
 
75
typedef unsigned char *POINTER;
 
76
typedef const unsigned char *CONST_POINTER;
 
77
 
 
78
 
 
79
/* UINT4 defines a four byte word */
 
80
typedef unsigned int UINT4;
 
81
 
 
82
 
 
83
/* MD5 context. */
 
84
typedef struct {
 
85
  UINT4 state[4];                                   /* state (ABCD) */
 
86
  UINT4 count[2];        /* number of bits, modulo 2^64 (lsb first) */
 
87
  unsigned char buffer[64];                         /* input buffer */
 
88
} MD5_CTX;
 
89
 
 
90
static void MD5Init (MD5_CTX *context);      /* context */
 
91
static void MD5Update ( MD5_CTX *context,                                        /* context */
 
92
                        const unsigned char *input,                              /* input block */
 
93
                        unsigned int inputLen);                     /* length of input block */
 
94
static void MD5Final ( unsigned char digest[16],                         /* message digest */
 
95
                       MD5_CTX *context);                              /* context */
 
96
 
 
97
/* Constants for MD5Transform routine. */
 
98
 
 
99
#define S11 7
 
100
#define S12 12
 
101
#define S13 17
 
102
#define S14 22
 
103
#define S21 5
 
104
#define S22 9
 
105
#define S23 14
 
106
#define S24 20
 
107
#define S31 4
 
108
#define S32 11
 
109
#define S33 16
 
110
#define S34 23
 
111
#define S41 6
 
112
#define S42 10
 
113
#define S43 15
 
114
#define S44 21
 
115
 
 
116
 
 
117
static void MD5Transform (UINT4 state[4],
 
118
                          const unsigned char block[64]);
 
119
static void Encode (unsigned char *output,
 
120
                    UINT4 *input,
 
121
                    unsigned int len);
 
122
static void Decode(UINT4 *output, const unsigned char *input, unsigned int len);
 
123
 
 
124
static unsigned char PADDING[64] = {
 
125
  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
126
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
127
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 
128
};
 
129
 
 
130
/* F, G, H and I are basic MD5 functions.
 
131
 */
 
132
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
 
133
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
 
134
#define H(x, y, z) ((x) ^ (y) ^ (z))
 
135
#define I(x, y, z) ((y) ^ ((x) | (~z)))
 
136
 
 
137
/* ROTATE_LEFT rotates x left n bits.
 
138
 */
 
139
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
 
140
 
 
141
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
 
142
Rotation is separate from addition to prevent recomputation.
 
143
 */
 
144
#define FF(a, b, c, d, x, s, ac) { \
 
145
 (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
 
146
 (a) = ROTATE_LEFT ((a), (s)); \
 
147
 (a) += (b); \
 
148
  }
 
149
#define GG(a, b, c, d, x, s, ac) { \
 
150
 (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
 
151
 (a) = ROTATE_LEFT ((a), (s)); \
 
152
 (a) += (b); \
 
153
  }
 
154
#define HH(a, b, c, d, x, s, ac) { \
 
155
 (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
 
156
 (a) = ROTATE_LEFT ((a), (s)); \
 
157
 (a) += (b); \
 
158
  }
 
159
#define II(a, b, c, d, x, s, ac) { \
 
160
 (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
 
161
 (a) = ROTATE_LEFT ((a), (s)); \
 
162
 (a) += (b); \
 
163
  }
 
164
 
 
165
 
 
166
/*
 
167
  Just a simple method for getting the signature
 
168
  result must be == 16
 
169
*/
 
170
void md5_signature(const unsigned char *key, unsigned int length, unsigned char *result)
 
171
{
 
172
    MD5_CTX my_md5;
 
173
 
 
174
    MD5Init(&my_md5);
 
175
    (void)MD5Update(&my_md5, key, length);
 
176
    MD5Final(result, &my_md5);
 
177
}
 
178
 
 
179
/* MD5 initialization. Begins an MD5 operation, writing a new context.
 
180
 */
 
181
static void MD5Init (MD5_CTX *context)      /* context */
 
182
{
 
183
  context->count[0] = context->count[1] = 0;
 
184
  /* Load magic initialization constants.
 
185
*/
 
186
  context->state[0] = 0x67452301;
 
187
  context->state[1] = 0xefcdab89;
 
188
  context->state[2] = 0x98badcfe;
 
189
  context->state[3] = 0x10325476;
 
190
}
 
191
 
 
192
/* MD5 block update operation. Continues an MD5 message-digest
 
193
  operation, processing another message block, and updating the
 
194
  context.
 
195
 */
 
196
 
 
197
static void MD5Update (
 
198
                       MD5_CTX *context,                                        /* context */
 
199
                       const unsigned char *input,                              /* input block */
 
200
                       unsigned int inputLen)                     /* length of input block */
 
201
{
 
202
  unsigned int i, idx, partLen;
 
203
 
 
204
  /* Compute number of bytes mod 64 */
 
205
  idx = (unsigned int)((context->count[0] >> 3) & 0x3F);
 
206
 
 
207
 
 
208
  /* Update number of bits */
 
209
  if ((context->count[0] += ((UINT4)inputLen << 3))
 
210
      < ((UINT4)inputLen << 3))
 
211
    context->count[1]++;
 
212
  context->count[1] += ((UINT4)inputLen >> 29);
 
213
 
 
214
  partLen = 64 - idx;
 
215
 
 
216
  /* Transform as many times as possible.
 
217
*/
 
218
  if (inputLen >= partLen) {
 
219
    memcpy((POINTER)&context->buffer[idx], (CONST_POINTER)input, partLen);
 
220
    MD5Transform(context->state, context->buffer);
 
221
 
 
222
    for (i = partLen; i + 63 < inputLen; i += 64)
 
223
      MD5Transform (context->state, (CONST_POINTER)&input[i]);
 
224
 
 
225
    idx = 0;
 
226
  }
 
227
  else
 
228
    i = 0;
 
229
 
 
230
  /* Buffer remaining input */
 
231
  memcpy((POINTER)&context->buffer[idx], (CONST_POINTER)&input[i],
 
232
         inputLen-i);
 
233
}
 
234
 
 
235
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
 
236
  the message digest and zeroizing the context.
 
237
 */
 
238
 
 
239
static void MD5Final (
 
240
                      unsigned char digest[16],                         /* message digest */
 
241
                      MD5_CTX *context)                              /* context */
 
242
{
 
243
  unsigned char bits[8];
 
244
  unsigned int idx, padLen;
 
245
 
 
246
  /* Save number of bits */
 
247
  Encode (bits, context->count, 8);
 
248
 
 
249
  /* Pad out to 56 mod 64.
 
250
*/
 
251
  idx = (unsigned int)((context->count[0] >> 3) & 0x3f);
 
252
  padLen = (idx < 56) ? (56 - idx) : (120 - idx);
 
253
  MD5Update (context, PADDING, padLen);
 
254
 
 
255
  /* Append length (before padding) */
 
256
  MD5Update (context, bits, 8);
 
257
 
 
258
  /* Store state in digest */
 
259
  Encode (digest, context->state, 16);
 
260
 
 
261
  /* Zeroize sensitive information.
 
262
*/
 
263
  memset((POINTER)context, 0, sizeof (*context));
 
264
}
 
265
 
 
266
/* MD5 basic transformation. Transforms state based on block.
 
267
 */
 
268
static void MD5Transform (
 
269
                          UINT4 state[4],
 
270
                          const unsigned char block[64])
 
271
{
 
272
  UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
 
273
 
 
274
  Decode (x, block, 64);
 
275
 
 
276
  /* Round 1 */
 
277
  FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
 
278
  FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
 
279
  FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
 
280
  FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
 
281
  FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
 
282
  FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
 
283
  FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
 
284
  FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
 
285
  FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
 
286
  FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
 
287
  FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
 
288
  FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
 
289
  FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
 
290
  FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
 
291
  FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
 
292
  FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
 
293
 
 
294
 /* Round 2 */
 
295
  GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
 
296
  GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
 
297
  GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
 
298
  GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
 
299
  GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
 
300
  GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
 
301
  GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
 
302
  GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
 
303
  GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
 
304
  GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
 
305
  GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
 
306
  GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
 
307
  GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
 
308
  GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
 
309
  GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
 
310
  GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
 
311
 
 
312
  /* Round 3 */
 
313
  HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
 
314
  HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
 
315
  HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
 
316
  HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
 
317
  HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
 
318
  HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
 
319
  HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
 
320
  HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
 
321
  HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
 
322
  HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
 
323
  HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
 
324
  HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
 
325
  HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
 
326
  HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
 
327
  HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
 
328
  HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
 
329
 
 
330
  /* Round 4 */
 
331
  II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
 
332
  II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
 
333
  II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
 
334
  II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
 
335
  II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
 
336
  II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
 
337
  II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
 
338
  II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
 
339
  II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
 
340
  II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
 
341
  II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
 
342
  II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
 
343
  II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
 
344
  II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
 
345
  II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
 
346
  II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
 
347
 
 
348
 
 
349
  state[0] += a;
 
350
  state[1] += b;
 
351
  state[2] += c;
 
352
  state[3] += d;
 
353
 
 
354
  /* Zeroize sensitive information.
 
355
*/
 
356
  memset((POINTER)x, 0, sizeof (x));
 
357
}
 
358
 
 
359
/* Encodes input (UINT4) into output (unsigned char). Assumes len is
 
360
  a multiple of 4.
 
361
 */
 
362
static void Encode (
 
363
unsigned char *output,
 
364
UINT4 *input,
 
365
unsigned int len)
 
366
{
 
367
  unsigned int i, j;
 
368
 
 
369
  for (i = 0, j = 0; j < len; i++, j += 4) {
 
370
 output[j] = (unsigned char)(input[i] & 0xff);
 
371
 output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
 
372
 output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
 
373
 output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
 
374
  }
 
375
}
 
376
 
 
377
 
 
378
/* Decodes input (unsigned char) into output (UINT4). Assumes len is
 
379
  a multiple of 4.
 
380
 */
 
381
static void Decode (
 
382
                    UINT4 *output,
 
383
                    const unsigned char *input,
 
384
                    unsigned int len)
 
385
{
 
386
  unsigned int i, j;
 
387
 
 
388
  for (i = 0, j = 0; j < len; i++, j += 4)
 
389
    output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
 
390
      (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
 
391
}
 
392
 
 
393
uint32_t hashkit_md5(const char *key, size_t key_length, void *context)
 
394
{
 
395
  unsigned char results[16];
 
396
  (void)context;
 
397
 
 
398
  md5_signature((unsigned char*)key, (unsigned int)key_length, results);
 
399
 
 
400
  return ((uint32_t) (results[3] & 0xFF) << 24)
 
401
    | ((uint32_t) (results[2] & 0xFF) << 16)
 
402
    | ((uint32_t) (results[1] & 0xFF) << 8)
 
403
    | (results[0] & 0xFF);
 
404
}