gloox 1.0.27
md5.cpp
1/*
2 Copyright (c) 2006-2023 by Jakob Schröter <js@camaya.net>
3 This file is part of the gloox library. http://camaya.net/gloox
4
5 This software is distributed under a license. The full license
6 agreement can be found in the file LICENSE in this distribution.
7 This software may not be copied, modified, sold or distributed
8 other than expressed in the named license agreement.
9
10 This software is distributed without any warranty.
11*/
12
13/*
14 This class is based on a C implementation of the MD5 algorithm written by
15 L. Peter Deutsch.
16 The full notice as shipped with the original verson is included below.
17*/
18
19/*
20 Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
21
22 This software is provided 'as-is', without any express or implied
23 warranty. In no event will the authors be held liable for any damages
24 arising from the use of this software.
25
26 Permission is granted to anyone to use this software for any purpose,
27 including commercial applications, and to alter it and redistribute it
28 freely, subject to the following restrictions:
29
30 1. The origin of this software must not be misrepresented; you must not
31 claim that you wrote the original software. If you use this software
32 in a product, an acknowledgment in the product documentation would be
33 appreciated but is not required.
34 2. Altered source versions must be plainly marked as such, and must not be
35 misrepresented as being the original software.
36 3. This notice may not be removed or altered from any source distribution.
37
38 L. Peter Deutsch
39 ghost@aladdin.com
40
41 */
42/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
43/*
44 Independent implementation of MD5 (RFC 1321).
45
46 This code implements the MD5 Algorithm defined in RFC 1321, whose
47 text is available at
48 http://www.ietf.org/rfc/rfc1321.txt
49 The code is derived from the text of the RFC, including the test suite
50 (section A.5) but excluding the rest of Appendix A. It does not include
51 any code or documentation that is identified in the RFC as being
52 copyrighted.
53
54 The original and principal author of md5.c is L. Peter Deutsch
55 <ghost@aladdin.com>. Other authors are noted in the change history
56 that follows (in reverse chronological order):
57
58 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
59 either statically or dynamically; added missing #include <string.h>
60 in library.
61 2002-03-11 lpd Corrected argument list for main(), and added int return
62 type, in test program and T value program.
63 2002-02-21 lpd Added missing #include <stdio.h> in test program.
64 2000-07-03 lpd Patched to eliminate warnings about "constant is
65 unsigned in ANSI C, signed in traditional"; made test program
66 self-checking.
67 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
68 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
69 1999-05-03 lpd Original version.
70 */
71
72#include "config.h"
73
74#include "md5.h"
75
76#include <cstdio>
77#include <string.h>
78
79#include <cstdio> // [s]print[f]
80
81namespace gloox
82{
83// #undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
84// #ifdef ARCH_IS_BIG_ENDIAN
85// # define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
86// #else
87// # define BYTE_ORDER 0
88// #endif
89
90#undef BYTE_ORDER
91#define BYTE_ORDER 0
92
93#define T_MASK (static_cast<unsigned int>(~0))
94#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
95#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
96#define T3 0x242070db
97#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
98#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
99#define T6 0x4787c62a
100#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
101#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
102#define T9 0x698098d8
103#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
104#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
105#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
106#define T13 0x6b901122
107#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
108#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
109#define T16 0x49b40821
110#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
111#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
112#define T19 0x265e5a51
113#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
114#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
115#define T22 0x02441453
116#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
117#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
118#define T25 0x21e1cde6
119#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
120#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
121#define T28 0x455a14ed
122#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
123#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
124#define T31 0x676f02d9
125#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
126#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
127#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
128#define T35 0x6d9d6122
129#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
130#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
131#define T38 0x4bdecfa9
132#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
133#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
134#define T41 0x289b7ec6
135#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
136#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
137#define T44 0x04881d05
138#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
139#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
140#define T47 0x1fa27cf8
141#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
142#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
143#define T50 0x432aff97
144#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
145#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
146#define T53 0x655b59c3
147#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
148#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
149#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
150#define T57 0x6fa87e4f
151#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
152#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
153#define T60 0x4e0811a1
154#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
155#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
156#define T63 0x2ad7d2bb
157#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
158
159
160 const unsigned char MD5::pad[64] =
161 {
162 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
163 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
164 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
165 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
166 };
167
169 : m_finished( false )
170 {
171 init();
172 }
173
175 {
176 }
177
178 void MD5::process( const unsigned char* data /*[64]*/ )
179 {
180 unsigned int a = m_state.abcd[0];
181 unsigned int b = m_state.abcd[1];
182 unsigned int c = m_state.abcd[2];
183 unsigned int d = m_state.abcd[3];
184 unsigned int t;
185#if BYTE_ORDER > 0
186 /* Define storage only for big-endian CPUs. */
187 unsigned int X[16];
188#else
189 /* Define storage for little-endian or both types of CPUs. */
190 unsigned int xbuf[16];
191 const unsigned int *X;
192#endif
193
194 {
195#if BYTE_ORDER == 0
196 /*
197 * Determine dynamically whether this is a big-endian or
198 * little-endian machine, since we can use a more efficient
199 * algorithm on the latter.
200 */
201 static const int w = 1;
202
203 if( *(reinterpret_cast<const unsigned char *>( &w )) ) /* dynamic little-endian */
204#endif
205#if BYTE_ORDER <= 0 /* little-endian */
206 {
207 /*
208 * On little-endian machines, we can process properly aligned
209 * data without copying it.
210 */
211 if( !((data - reinterpret_cast<const unsigned char*>( 0 )) & 3) )
212 {
213 /* data are properly aligned */
214 X = reinterpret_cast<const unsigned int*>( data );
215 }
216 else
217 {
218 /* not aligned */
219 memcpy( xbuf, data, 64 );
220 X = xbuf;
221 }
222 }
223#endif
224#if BYTE_ORDER == 0
225 else // dynamic big-endian
226#endif
227#if BYTE_ORDER >= 0 // big-endian
228 {
229 /*
230 * On big-endian machines, we must arrange the bytes in the
231 * right order.
232 */
233 const unsigned char* xp = data;
234 int i;
235
236# if BYTE_ORDER == 0
237 X = xbuf; // (dynamic only)
238# else
239# define xbuf X /* (static only) */
240# endif
241 for( i = 0; i < 16; ++i, xp += 4 )
242 xbuf[i] = xp[0] + ( xp[1] << 8 ) + ( xp[2] << 16 ) + ( xp[3] << 24 );
243 }
244#endif
245 }
246
247#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
248
249 /* Round 1. */
250 /* Let [abcd k s i] denote the operation
251 a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
252#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
253#define SET(a, b, c, d, k, s, Ti)\
254 t = a + F(b,c,d) + X[k] + Ti;\
255 a = ROTATE_LEFT(t, s) + b
256 /* Do the following 16 operations. */
257 SET(a, b, c, d, 0, 7, T1);
258 SET(d, a, b, c, 1, 12, T2);
259 SET(c, d, a, b, 2, 17, T3);
260 SET(b, c, d, a, 3, 22, T4);
261 SET(a, b, c, d, 4, 7, T5);
262 SET(d, a, b, c, 5, 12, T6);
263 SET(c, d, a, b, 6, 17, T7);
264 SET(b, c, d, a, 7, 22, T8);
265 SET(a, b, c, d, 8, 7, T9);
266 SET(d, a, b, c, 9, 12, T10);
267 SET(c, d, a, b, 10, 17, T11);
268 SET(b, c, d, a, 11, 22, T12);
269 SET(a, b, c, d, 12, 7, T13);
270 SET(d, a, b, c, 13, 12, T14);
271 SET(c, d, a, b, 14, 17, T15);
272 SET(b, c, d, a, 15, 22, T16);
273#undef SET
274
275 /* Round 2. */
276 /* Let [abcd k s i] denote the operation
277 a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
278#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
279#define SET(a, b, c, d, k, s, Ti)\
280 t = a + G(b,c,d) + X[k] + Ti;\
281 a = ROTATE_LEFT(t, s) + b
282 /* Do the following 16 operations. */
283 SET(a, b, c, d, 1, 5, T17);
284 SET(d, a, b, c, 6, 9, T18);
285 SET(c, d, a, b, 11, 14, T19);
286 SET(b, c, d, a, 0, 20, T20);
287 SET(a, b, c, d, 5, 5, T21);
288 SET(d, a, b, c, 10, 9, T22);
289 SET(c, d, a, b, 15, 14, T23);
290 SET(b, c, d, a, 4, 20, T24);
291 SET(a, b, c, d, 9, 5, T25);
292 SET(d, a, b, c, 14, 9, T26);
293 SET(c, d, a, b, 3, 14, T27);
294 SET(b, c, d, a, 8, 20, T28);
295 SET(a, b, c, d, 13, 5, T29);
296 SET(d, a, b, c, 2, 9, T30);
297 SET(c, d, a, b, 7, 14, T31);
298 SET(b, c, d, a, 12, 20, T32);
299#undef SET
300
301 /* Round 3. */
302 /* Let [abcd k s t] denote the operation
303 a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
304#define H(x, y, z) ((x) ^ (y) ^ (z))
305#define SET(a, b, c, d, k, s, Ti)\
306 t = a + H(b,c,d) + X[k] + Ti;\
307 a = ROTATE_LEFT(t, s) + b
308 /* Do the following 16 operations. */
309 SET(a, b, c, d, 5, 4, T33);
310 SET(d, a, b, c, 8, 11, T34);
311 SET(c, d, a, b, 11, 16, T35);
312 SET(b, c, d, a, 14, 23, T36);
313 SET(a, b, c, d, 1, 4, T37);
314 SET(d, a, b, c, 4, 11, T38);
315 SET(c, d, a, b, 7, 16, T39);
316 SET(b, c, d, a, 10, 23, T40);
317 SET(a, b, c, d, 13, 4, T41);
318 SET(d, a, b, c, 0, 11, T42);
319 SET(c, d, a, b, 3, 16, T43);
320 SET(b, c, d, a, 6, 23, T44);
321 SET(a, b, c, d, 9, 4, T45);
322 SET(d, a, b, c, 12, 11, T46);
323 SET(c, d, a, b, 15, 16, T47);
324 SET(b, c, d, a, 2, 23, T48);
325#undef SET
326
327 /* Round 4. */
328 /* Let [abcd k s t] denote the operation
329 a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
330#define I(x, y, z) ((y) ^ ((x) | ~(z)))
331#define SET(a, b, c, d, k, s, Ti)\
332 t = a + I(b,c,d) + X[k] + Ti;\
333 a = ROTATE_LEFT(t, s) + b
334 /* Do the following 16 operations. */
335 SET(a, b, c, d, 0, 6, T49);
336 SET(d, a, b, c, 7, 10, T50);
337 SET(c, d, a, b, 14, 15, T51);
338 SET(b, c, d, a, 5, 21, T52);
339 SET(a, b, c, d, 12, 6, T53);
340 SET(d, a, b, c, 3, 10, T54);
341 SET(c, d, a, b, 10, 15, T55);
342 SET(b, c, d, a, 1, 21, T56);
343 SET(a, b, c, d, 8, 6, T57);
344 SET(d, a, b, c, 15, 10, T58);
345 SET(c, d, a, b, 6, 15, T59);
346 SET(b, c, d, a, 13, 21, T60);
347 SET(a, b, c, d, 4, 6, T61);
348 SET(d, a, b, c, 11, 10, T62);
349 SET(c, d, a, b, 2, 15, T63);
350 SET(b, c, d, a, 9, 21, T64);
351#undef SET
352
353 /* Then perform the following additions. (That is increment each
354 of the four registers by the value it had before this block
355 was started.) */
356 m_state.abcd[0] += a;
357 m_state.abcd[1] += b;
358 m_state.abcd[2] += c;
359 m_state.abcd[3] += d;
360 }
361
362 void MD5::init()
363 {
364 m_finished = false;
365 m_state.count[0] = 0;
366 m_state.count[1] = 0;
367 m_state.abcd[0] = 0x67452301;
368 m_state.abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
369 m_state.abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
370 m_state.abcd[3] = 0x10325476;
371 }
372
373 void MD5::feed( const std::string& data )
374 {
375 feed( reinterpret_cast<const unsigned char*>( data.c_str() ), static_cast<int>( data.length() ) );
376 }
377
378 void MD5::feed( const unsigned char* data, int bytes )
379 {
380 const unsigned char* p = data;
381 int left = bytes;
382 int offset = ( m_state.count[0] >> 3 ) & 63;
383 unsigned int nbits = static_cast<unsigned int>( bytes << 3 );
384
385 if( bytes <= 0 )
386 return;
387
388 /* Update the message length. */
389 m_state.count[1] += bytes >> 29;
390 m_state.count[0] += nbits;
391 if( m_state.count[0] < nbits )
392 m_state.count[1]++;
393
394 /* Process an initial partial block. */
395 if( offset )
396 {
397 int copy = ( offset + bytes > 64 ? 64 - offset : bytes );
398
399 memcpy( m_state.buf + offset, p, copy );
400 if( offset + copy < 64 )
401 return;
402 p += copy;
403 left -= copy;
404 process( m_state.buf );
405 }
406
407 /* Process full blocks. */
408 for( ; left >= 64; p += 64, left -= 64 )
409 process( p );
410
411 /* Process a final partial block. */
412 if( left )
413 memcpy( m_state.buf, p, left );
414 }
415
417 {
418 if( m_finished )
419 return;
420
421 unsigned char data[8];
422
423 /* Save the length before padding. */
424 for( int i = 0; i < 8; ++i )
425 data[i] = static_cast<unsigned char>( m_state.count[i >> 2] >> ( ( i & 3 ) << 3 ) );
426
427 /* Pad to 56 bytes mod 64. */
428 feed( pad, ( ( 55 - ( m_state.count[0] >> 3 ) ) & 63 ) + 1 );
429
430 /* Append the length. */
431 feed( data, 8 );
432
433 m_finished = true;
434 }
435
436 const std::string MD5::hex()
437 {
438 if( !m_finished )
439 finalize();
440
441 char buf[33];
442
443 for( int i = 0; i < 16; ++i )
444 sprintf( buf + i * 2, "%02x", static_cast<unsigned char>( m_state.abcd[i >> 2] >> ( ( i & 3 ) << 3 ) ) );
445
446 return std::string( buf, 32 );
447 }
448
449 const std::string MD5::binary()
450 {
451 if( !m_finished )
452 finalize();
453
454 unsigned char digest[16];
455 for( int i = 0; i < 16; ++i )
456 digest[i] = static_cast<unsigned char>( m_state.abcd[i >> 2] >> ( ( i & 3 ) << 3 ) );
457
458 return std::string( reinterpret_cast<char*>( digest ), 16 );
459 }
460
462 {
463 init();
464 }
465
466}
void feed(const unsigned char *data, int bytes)
Definition md5.cpp:378
void finalize()
Definition md5.cpp:416
virtual ~MD5()
Definition md5.cpp:174
const std::string binary()
Definition md5.cpp:449
const std::string hex()
Definition md5.cpp:436
void reset()
Definition md5.cpp:461
The namespace for the gloox library.
Definition adhoc.cpp:28