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