WebSocket++  0.8.3-dev
C++ websocket client/server library
md5.hpp
1 /*
2  md5.hpp is a reformulation of the md5.h and md5.c code from
3  http://www.opensource.apple.com/source/cups/cups-59/cups/md5.c to allow it to
4  function as a component of a header only library. This conversion was done by
5  Peter Thorson (webmaster@zaphoyd.com) in 2012 for the WebSocket++ project. The
6  changes are released under the same license as the original (listed below)
7 */
8 /*
9  Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
10 
11  This software is provided 'as-is', without any express or implied
12  warranty. In no event will the authors be held liable for any damages
13  arising from the use of this software.
14 
15  Permission is granted to anyone to use this software for any purpose,
16  including commercial applications, and to alter it and redistribute it
17  freely, subject to the following restrictions:
18 
19  1. The origin of this software must not be misrepresented; you must not
20  claim that you wrote the original software. If you use this software
21  in a product, an acknowledgment in the product documentation would be
22  appreciated but is not required.
23  2. Altered source versions must be plainly marked as such, and must not be
24  misrepresented as being the original software.
25  3. This notice may not be removed or altered from any source distribution.
26 
27  L. Peter Deutsch
28  ghost@aladdin.com
29 
30  */
31 /* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
32 /*
33  Independent implementation of MD5 (RFC 1321).
34 
35  This code implements the MD5 Algorithm defined in RFC 1321, whose
36  text is available at
37  http://www.ietf.org/rfc/rfc1321.txt
38  The code is derived from the text of the RFC, including the test suite
39  (section A.5) but excluding the rest of Appendix A. It does not include
40  any code or documentation that is identified in the RFC as being
41  copyrighted.
42 
43  The original and principal author of md5.h is L. Peter Deutsch
44  <ghost@aladdin.com>. Other authors are noted in the change history
45  that follows (in reverse chronological order):
46 
47  2002-04-13 lpd Removed support for non-ANSI compilers; removed
48  references to Ghostscript; clarified derivation from RFC 1321;
49  now handles byte order either statically or dynamically.
50  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
51  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
52  added conditionalization for C++ compilation from Martin
53  Purschke <purschke@bnl.gov>.
54  1999-05-03 lpd Original version.
55  */
56 
57 #ifndef WEBSOCKETPP_COMMON_MD5_HPP
58 #define WEBSOCKETPP_COMMON_MD5_HPP
59 
60 /*
61  * This package supports both compile-time and run-time determination of CPU
62  * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
63  * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
64  * defined as non-zero, the code will be compiled to run only on big-endian
65  * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
66  * run on either big- or little-endian CPUs, but will run slightly less
67  * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
68  */
69 
70 #include <stddef.h>
71 #include <string>
72 #include <cstring>
73 
74 namespace websocketpp {
75 /// Provides MD5 hashing functionality
76 namespace md5 {
77 
78 typedef unsigned char md5_byte_t; /* 8-bit byte */
79 typedef unsigned int md5_word_t; /* 32-bit word */
80 
81 /* Define the state of the MD5 Algorithm. */
82 typedef struct md5_state_s {
83  md5_word_t count[2]; /* message length in bits, lsw first */
84  md5_word_t abcd[4]; /* digest buffer */
85  md5_byte_t buf[64]; /* accumulate block */
86 } md5_state_t;
87 
88 /* Initialize the algorithm. */
89 inline void md5_init(md5_state_t *pms);
90 
91 /* Append a string to the message. */
92 inline void md5_append(md5_state_t *pms, md5_byte_t const * data, size_t nbytes);
93 
94 /* Finish the message and return the digest. */
95 inline void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
96 
97 #undef ZSW_MD5_BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
98 #ifdef ARCH_IS_BIG_ENDIAN
99 # define ZSW_MD5_BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
100 #else
101 # define ZSW_MD5_BYTE_ORDER 0
102 #endif
103 
104 #define ZSW_MD5_T_MASK ((md5_word_t)~0)
105 #define ZSW_MD5_T1 /* 0xd76aa478 */ (ZSW_MD5_T_MASK ^ 0x28955b87)
106 #define ZSW_MD5_T2 /* 0xe8c7b756 */ (ZSW_MD5_T_MASK ^ 0x173848a9)
107 #define ZSW_MD5_T3 0x242070db
108 #define ZSW_MD5_T4 /* 0xc1bdceee */ (ZSW_MD5_T_MASK ^ 0x3e423111)
109 #define ZSW_MD5_T5 /* 0xf57c0faf */ (ZSW_MD5_T_MASK ^ 0x0a83f050)
110 #define ZSW_MD5_T6 0x4787c62a
111 #define ZSW_MD5_T7 /* 0xa8304613 */ (ZSW_MD5_T_MASK ^ 0x57cfb9ec)
112 #define ZSW_MD5_T8 /* 0xfd469501 */ (ZSW_MD5_T_MASK ^ 0x02b96afe)
113 #define ZSW_MD5_T9 0x698098d8
114 #define ZSW_MD5_T10 /* 0x8b44f7af */ (ZSW_MD5_T_MASK ^ 0x74bb0850)
115 #define ZSW_MD5_T11 /* 0xffff5bb1 */ (ZSW_MD5_T_MASK ^ 0x0000a44e)
116 #define ZSW_MD5_T12 /* 0x895cd7be */ (ZSW_MD5_T_MASK ^ 0x76a32841)
117 #define ZSW_MD5_T13 0x6b901122
118 #define ZSW_MD5_T14 /* 0xfd987193 */ (ZSW_MD5_T_MASK ^ 0x02678e6c)
119 #define ZSW_MD5_T15 /* 0xa679438e */ (ZSW_MD5_T_MASK ^ 0x5986bc71)
120 #define ZSW_MD5_T16 0x49b40821
121 #define ZSW_MD5_T17 /* 0xf61e2562 */ (ZSW_MD5_T_MASK ^ 0x09e1da9d)
122 #define ZSW_MD5_T18 /* 0xc040b340 */ (ZSW_MD5_T_MASK ^ 0x3fbf4cbf)
123 #define ZSW_MD5_T19 0x265e5a51
124 #define ZSW_MD5_T20 /* 0xe9b6c7aa */ (ZSW_MD5_T_MASK ^ 0x16493855)
125 #define ZSW_MD5_T21 /* 0xd62f105d */ (ZSW_MD5_T_MASK ^ 0x29d0efa2)
126 #define ZSW_MD5_T22 0x02441453
127 #define ZSW_MD5_T23 /* 0xd8a1e681 */ (ZSW_MD5_T_MASK ^ 0x275e197e)
128 #define ZSW_MD5_T24 /* 0xe7d3fbc8 */ (ZSW_MD5_T_MASK ^ 0x182c0437)
129 #define ZSW_MD5_T25 0x21e1cde6
130 #define ZSW_MD5_T26 /* 0xc33707d6 */ (ZSW_MD5_T_MASK ^ 0x3cc8f829)
131 #define ZSW_MD5_T27 /* 0xf4d50d87 */ (ZSW_MD5_T_MASK ^ 0x0b2af278)
132 #define ZSW_MD5_T28 0x455a14ed
133 #define ZSW_MD5_T29 /* 0xa9e3e905 */ (ZSW_MD5_T_MASK ^ 0x561c16fa)
134 #define ZSW_MD5_T30 /* 0xfcefa3f8 */ (ZSW_MD5_T_MASK ^ 0x03105c07)
135 #define ZSW_MD5_T31 0x676f02d9
136 #define ZSW_MD5_T32 /* 0x8d2a4c8a */ (ZSW_MD5_T_MASK ^ 0x72d5b375)
137 #define ZSW_MD5_T33 /* 0xfffa3942 */ (ZSW_MD5_T_MASK ^ 0x0005c6bd)
138 #define ZSW_MD5_T34 /* 0x8771f681 */ (ZSW_MD5_T_MASK ^ 0x788e097e)
139 #define ZSW_MD5_T35 0x6d9d6122
140 #define ZSW_MD5_T36 /* 0xfde5380c */ (ZSW_MD5_T_MASK ^ 0x021ac7f3)
141 #define ZSW_MD5_T37 /* 0xa4beea44 */ (ZSW_MD5_T_MASK ^ 0x5b4115bb)
142 #define ZSW_MD5_T38 0x4bdecfa9
143 #define ZSW_MD5_T39 /* 0xf6bb4b60 */ (ZSW_MD5_T_MASK ^ 0x0944b49f)
144 #define ZSW_MD5_T40 /* 0xbebfbc70 */ (ZSW_MD5_T_MASK ^ 0x4140438f)
145 #define ZSW_MD5_T41 0x289b7ec6
146 #define ZSW_MD5_T42 /* 0xeaa127fa */ (ZSW_MD5_T_MASK ^ 0x155ed805)
147 #define ZSW_MD5_T43 /* 0xd4ef3085 */ (ZSW_MD5_T_MASK ^ 0x2b10cf7a)
148 #define ZSW_MD5_T44 0x04881d05
149 #define ZSW_MD5_T45 /* 0xd9d4d039 */ (ZSW_MD5_T_MASK ^ 0x262b2fc6)
150 #define ZSW_MD5_T46 /* 0xe6db99e5 */ (ZSW_MD5_T_MASK ^ 0x1924661a)
151 #define ZSW_MD5_T47 0x1fa27cf8
152 #define ZSW_MD5_T48 /* 0xc4ac5665 */ (ZSW_MD5_T_MASK ^ 0x3b53a99a)
153 #define ZSW_MD5_T49 /* 0xf4292244 */ (ZSW_MD5_T_MASK ^ 0x0bd6ddbb)
154 #define ZSW_MD5_T50 0x432aff97
155 #define ZSW_MD5_T51 /* 0xab9423a7 */ (ZSW_MD5_T_MASK ^ 0x546bdc58)
156 #define ZSW_MD5_T52 /* 0xfc93a039 */ (ZSW_MD5_T_MASK ^ 0x036c5fc6)
157 #define ZSW_MD5_T53 0x655b59c3
158 #define ZSW_MD5_T54 /* 0x8f0ccc92 */ (ZSW_MD5_T_MASK ^ 0x70f3336d)
159 #define ZSW_MD5_T55 /* 0xffeff47d */ (ZSW_MD5_T_MASK ^ 0x00100b82)
160 #define ZSW_MD5_T56 /* 0x85845dd1 */ (ZSW_MD5_T_MASK ^ 0x7a7ba22e)
161 #define ZSW_MD5_T57 0x6fa87e4f
162 #define ZSW_MD5_T58 /* 0xfe2ce6e0 */ (ZSW_MD5_T_MASK ^ 0x01d3191f)
163 #define ZSW_MD5_T59 /* 0xa3014314 */ (ZSW_MD5_T_MASK ^ 0x5cfebceb)
164 #define ZSW_MD5_T60 0x4e0811a1
165 #define ZSW_MD5_T61 /* 0xf7537e82 */ (ZSW_MD5_T_MASK ^ 0x08ac817d)
166 #define ZSW_MD5_T62 /* 0xbd3af235 */ (ZSW_MD5_T_MASK ^ 0x42c50dca)
167 #define ZSW_MD5_T63 0x2ad7d2bb
168 #define ZSW_MD5_T64 /* 0xeb86d391 */ (ZSW_MD5_T_MASK ^ 0x14792c6e)
169 
170 static void md5_process(md5_state_t *pms, md5_byte_t const * data /*[64]*/) {
171  md5_word_t
172  a = pms->abcd[0], b = pms->abcd[1],
173  c = pms->abcd[2], d = pms->abcd[3];
174  md5_word_t t;
175 #if ZSW_MD5_BYTE_ORDER > 0
176  /* Define storage only for big-endian CPUs. */
177  md5_word_t X[16];
178 #else
179  /* Define storage for little-endian or both types of CPUs. */
180  md5_word_t xbuf[16];
181  md5_word_t const * X;
182 #endif
183 
184  {
185 #if ZSW_MD5_BYTE_ORDER == 0
186  /*
187  * Determine dynamically whether this is a big-endian or
188  * little-endian machine, since we can use a more efficient
189  * algorithm on the latter.
190  */
191  static int const w = 1;
192 
193  if (*((md5_byte_t const *)&w)) /* dynamic little-endian */
194 #endif
195 #if ZSW_MD5_BYTE_ORDER <= 0 /* little-endian */
196  {
197  /*
198  * On little-endian machines, we can process properly aligned
199  * data without copying it.
200  */
201  if (!((data - (md5_byte_t const *)0) & 3)) {
202  /* data are properly aligned */
203  X = (md5_word_t const *)data;
204  } else {
205  /* not aligned */
206  std::memcpy(xbuf, data, 64);
207  X = xbuf;
208  }
209  }
210 #endif
211 #if ZSW_MD5_BYTE_ORDER == 0
212  else /* dynamic big-endian */
213 #endif
214 #if ZSW_MD5_BYTE_ORDER >= 0 /* big-endian */
215  {
216  /*
217  * On big-endian machines, we must arrange the bytes in the
218  * right order.
219  */
220  const md5_byte_t *xp = data;
221  int i;
222 
223 # if ZSW_MD5_BYTE_ORDER == 0
224  X = xbuf; /* (dynamic only) */
225 # else
226 # define xbuf X /* (static only) */
227 # endif
228  for (i = 0; i < 16; ++i, xp += 4)
229  xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
230  }
231 #endif
232  }
233 
234 #define ZSW_MD5_ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
235 
236  /* Round 1. */
237  /* Let [abcd k s i] denote the operation
238  a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
239 #define ZSW_MD5_F(x, y, z) (((x) & (y)) | (~(x) & (z)))
240 #define SET(a, b, c, d, k, s, Ti)
241  t = a + ZSW_MD5_F(b,c,d) + X[k] + Ti;
242  a = ZSW_MD5_ROTATE_LEFT(t, s) + b
243  /* Do the following 16 operations. */
244  SET(a, b, c, d, 0, 7, ZSW_MD5_T1);
245  SET(d, a, b, c, 1, 12, ZSW_MD5_T2);
246  SET(c, d, a, b, 2, 17, ZSW_MD5_T3);
247  SET(b, c, d, a, 3, 22, ZSW_MD5_T4);
248  SET(a, b, c, d, 4, 7, ZSW_MD5_T5);
249  SET(d, a, b, c, 5, 12, ZSW_MD5_T6);
250  SET(c, d, a, b, 6, 17, ZSW_MD5_T7);
251  SET(b, c, d, a, 7, 22, ZSW_MD5_T8);
252  SET(a, b, c, d, 8, 7, ZSW_MD5_T9);
253  SET(d, a, b, c, 9, 12, ZSW_MD5_T10);
254  SET(c, d, a, b, 10, 17, ZSW_MD5_T11);
255  SET(b, c, d, a, 11, 22, ZSW_MD5_T12);
256  SET(a, b, c, d, 12, 7, ZSW_MD5_T13);
257  SET(d, a, b, c, 13, 12, ZSW_MD5_T14);
258  SET(c, d, a, b, 14, 17, ZSW_MD5_T15);
259  SET(b, c, d, a, 15, 22, ZSW_MD5_T16);
260 #undef SET
261 
262  /* Round 2. */
263  /* Let [abcd k s i] denote the operation
264  a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
265 #define ZSW_MD5_G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
266 #define SET(a, b, c, d, k, s, Ti)
267  t = a + ZSW_MD5_G(b,c,d) + X[k] + Ti;
268  a = ZSW_MD5_ROTATE_LEFT(t, s) + b
269  /* Do the following 16 operations. */
270  SET(a, b, c, d, 1, 5, ZSW_MD5_T17);
271  SET(d, a, b, c, 6, 9, ZSW_MD5_T18);
272  SET(c, d, a, b, 11, 14, ZSW_MD5_T19);
273  SET(b, c, d, a, 0, 20, ZSW_MD5_T20);
274  SET(a, b, c, d, 5, 5, ZSW_MD5_T21);
275  SET(d, a, b, c, 10, 9, ZSW_MD5_T22);
276  SET(c, d, a, b, 15, 14, ZSW_MD5_T23);
277  SET(b, c, d, a, 4, 20, ZSW_MD5_T24);
278  SET(a, b, c, d, 9, 5, ZSW_MD5_T25);
279  SET(d, a, b, c, 14, 9, ZSW_MD5_T26);
280  SET(c, d, a, b, 3, 14, ZSW_MD5_T27);
281  SET(b, c, d, a, 8, 20, ZSW_MD5_T28);
282  SET(a, b, c, d, 13, 5, ZSW_MD5_T29);
283  SET(d, a, b, c, 2, 9, ZSW_MD5_T30);
284  SET(c, d, a, b, 7, 14, ZSW_MD5_T31);
285  SET(b, c, d, a, 12, 20, ZSW_MD5_T32);
286 #undef SET
287 
288  /* Round 3. */
289  /* Let [abcd k s t] denote the operation
290  a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
291 #define ZSW_MD5_H(x, y, z) ((x) ^ (y) ^ (z))
292 #define SET(a, b, c, d, k, s, Ti)
293  t = a + ZSW_MD5_H(b,c,d) + X[k] + Ti;
294  a = ZSW_MD5_ROTATE_LEFT(t, s) + b
295  /* Do the following 16 operations. */
296  SET(a, b, c, d, 5, 4, ZSW_MD5_T33);
297  SET(d, a, b, c, 8, 11, ZSW_MD5_T34);
298  SET(c, d, a, b, 11, 16, ZSW_MD5_T35);
299  SET(b, c, d, a, 14, 23, ZSW_MD5_T36);
300  SET(a, b, c, d, 1, 4, ZSW_MD5_T37);
301  SET(d, a, b, c, 4, 11, ZSW_MD5_T38);
302  SET(c, d, a, b, 7, 16, ZSW_MD5_T39);
303  SET(b, c, d, a, 10, 23, ZSW_MD5_T40);
304  SET(a, b, c, d, 13, 4, ZSW_MD5_T41);
305  SET(d, a, b, c, 0, 11, ZSW_MD5_T42);
306  SET(c, d, a, b, 3, 16, ZSW_MD5_T43);
307  SET(b, c, d, a, 6, 23, ZSW_MD5_T44);
308  SET(a, b, c, d, 9, 4, ZSW_MD5_T45);
309  SET(d, a, b, c, 12, 11, ZSW_MD5_T46);
310  SET(c, d, a, b, 15, 16, ZSW_MD5_T47);
311  SET(b, c, d, a, 2, 23, ZSW_MD5_T48);
312 #undef SET
313 
314  /* Round 4. */
315  /* Let [abcd k s t] denote the operation
316  a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
317 #define ZSW_MD5_I(x, y, z) ((y) ^ ((x) | ~(z)))
318 #define SET(a, b, c, d, k, s, Ti)
319  t = a + ZSW_MD5_I(b,c,d) + X[k] + Ti;
320  a = ZSW_MD5_ROTATE_LEFT(t, s) + b
321  /* Do the following 16 operations. */
322  SET(a, b, c, d, 0, 6, ZSW_MD5_T49);
323  SET(d, a, b, c, 7, 10, ZSW_MD5_T50);
324  SET(c, d, a, b, 14, 15, ZSW_MD5_T51);
325  SET(b, c, d, a, 5, 21, ZSW_MD5_T52);
326  SET(a, b, c, d, 12, 6, ZSW_MD5_T53);
327  SET(d, a, b, c, 3, 10, ZSW_MD5_T54);
328  SET(c, d, a, b, 10, 15, ZSW_MD5_T55);
329  SET(b, c, d, a, 1, 21, ZSW_MD5_T56);
330  SET(a, b, c, d, 8, 6, ZSW_MD5_T57);
331  SET(d, a, b, c, 15, 10, ZSW_MD5_T58);
332  SET(c, d, a, b, 6, 15, ZSW_MD5_T59);
333  SET(b, c, d, a, 13, 21, ZSW_MD5_T60);
334  SET(a, b, c, d, 4, 6, ZSW_MD5_T61);
335  SET(d, a, b, c, 11, 10, ZSW_MD5_T62);
336  SET(c, d, a, b, 2, 15, ZSW_MD5_T63);
337  SET(b, c, d, a, 9, 21, ZSW_MD5_T64);
338 #undef SET
339 
340  /* Then perform the following additions. (That is increment each
341  of the four registers by the value it had before this block
342  was started.) */
343  pms->abcd[0] += a;
344  pms->abcd[1] += b;
345  pms->abcd[2] += c;
346  pms->abcd[3] += d;
347 }
348 
349 void md5_init(md5_state_t *pms) {
350  pms->count[0] = pms->count[1] = 0;
351  pms->abcd[0] = 0x67452301;
352  pms->abcd[1] = /*0xefcdab89*/ ZSW_MD5_T_MASK ^ 0x10325476;
353  pms->abcd[2] = /*0x98badcfe*/ ZSW_MD5_T_MASK ^ 0x67452301;
354  pms->abcd[3] = 0x10325476;
355 }
356 
357 void md5_append(md5_state_t *pms, md5_byte_t const * data, size_t nbytes) {
358  md5_byte_t const * p = data;
359  size_t left = nbytes;
360  int offset = (pms->count[0] >> 3) & 63;
361  md5_word_t nbits = (md5_word_t)(nbytes << 3);
362 
363  if (nbytes <= 0)
364  return;
365 
366  /* Update the message length. */
367  pms->count[1] += nbytes >> 29;
368  pms->count[0] += nbits;
369  if (pms->count[0] < nbits)
370  pms->count[1]++;
371 
372  /* Process an initial partial block. */
373  if (offset) {
374  int copy = (offset + nbytes > 64 ? 64 - offset : static_cast<int>(nbytes));
375 
376  std::memcpy(pms->buf + offset, p, copy);
377  if (offset + copy < 64)
378  return;
379  p += copy;
380  left -= copy;
381  md5_process(pms, pms->buf);
382  }
383 
384  /* Process full blocks. */
385  for (; left >= 64; p += 64, left -= 64)
386  md5_process(pms, p);
387 
388  /* Process a final partial block. */
389  if (left)
390  std::memcpy(pms->buf, p, left);
391 }
392 
393 void md5_finish(md5_state_t *pms, md5_byte_t digest[16]) {
394  static md5_byte_t const pad[64] = {
395  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
396  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
397  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
398  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
399  };
400  md5_byte_t data[8];
401  int i;
402 
403  /* Save the length before padding. */
404  for (i = 0; i < 8; ++i)
405  data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
406  /* Pad to 56 bytes mod 64. */
407  md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
408  /* Append the length. */
409  md5_append(pms, data, 8);
410  for (i = 0; i < 16; ++i)
411  digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
412 }
413 
414 // some convenience c++ functions
415 inline std::string md5_hash_string(std::string const & s) {
416  char digest[16];
417 
418  md5_state_t state;
419 
420  md5_init(&state);
421  md5_append(&state, (md5_byte_t const *)s.c_str(), s.size());
422  md5_finish(&state, (md5_byte_t *)digest);
423 
424  std::string ret;
425  ret.resize(16);
426  std::copy(digest,digest+16,ret.begin());
427 
428  return ret;
429 }
430 
431 const char hexval[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
432 
433 inline std::string md5_hash_hex(std::string const & input) {
434  std::string hash = md5_hash_string(input);
435  std::string hex;
436 
437  for (size_t i = 0; i < hash.size(); i++) {
438  hex.push_back(hexval[((hash[i] >> 4) & 0xF)]);
439  hex.push_back(hexval[(hash[i]) & 0x0F]);
440  }
441 
442  return hex;
443 }
444 
445 } // md5
446 } // websocketpp
447 
448 #endif // WEBSOCKETPP_COMMON_MD5_HPP
ZSW_MD5_T11
#define ZSW_MD5_T11
Definition: md5.hpp:115
ZSW_MD5_T8
#define ZSW_MD5_T8
Definition: md5.hpp:112
ZSW_MD5_T50
#define ZSW_MD5_T50
Definition: md5.hpp:154
ZSW_MD5_T54
#define ZSW_MD5_T54
Definition: md5.hpp:158
ZSW_MD5_T59
#define ZSW_MD5_T59
Definition: md5.hpp:163
websocketpp::md5
Provides MD5 hashing functionality.
Definition: md5.hpp:76
ZSW_MD5_T41
#define ZSW_MD5_T41
Definition: md5.hpp:145
ZSW_MD5_T35
#define ZSW_MD5_T35
Definition: md5.hpp:139
ZSW_MD5_T49
#define ZSW_MD5_T49
Definition: md5.hpp:153
ZSW_MD5_T52
#define ZSW_MD5_T52
Definition: md5.hpp:156
ZSW_MD5_T61
#define ZSW_MD5_T61
Definition: md5.hpp:165
ZSW_MD5_T27
#define ZSW_MD5_T27
Definition: md5.hpp:131
ZSW_MD5_T63
#define ZSW_MD5_T63
Definition: md5.hpp:167
ZSW_MD5_T39
#define ZSW_MD5_T39
Definition: md5.hpp:143
ZSW_MD5_T15
#define ZSW_MD5_T15
Definition: md5.hpp:119
ZSW_MD5_T62
#define ZSW_MD5_T62
Definition: md5.hpp:166
ZSW_MD5_T7
#define ZSW_MD5_T7
Definition: md5.hpp:111
ZSW_MD5_T21
#define ZSW_MD5_T21
Definition: md5.hpp:125
ZSW_MD5_T28
#define ZSW_MD5_T28
Definition: md5.hpp:132
SET
#define SET(a, b, c, d, k, s, Ti)
ZSW_MD5_T55
#define ZSW_MD5_T55
Definition: md5.hpp:159
ZSW_MD5_T42
#define ZSW_MD5_T42
Definition: md5.hpp:146
ZSW_MD5_T2
#define ZSW_MD5_T2
Definition: md5.hpp:106
ZSW_MD5_T40
#define ZSW_MD5_T40
Definition: md5.hpp:144
ZSW_MD5_T32
#define ZSW_MD5_T32
Definition: md5.hpp:136
ZSW_MD5_T5
#define ZSW_MD5_T5
Definition: md5.hpp:109
ZSW_MD5_T22
#define ZSW_MD5_T22
Definition: md5.hpp:126
ZSW_MD5_T29
#define ZSW_MD5_T29
Definition: md5.hpp:133
ZSW_MD5_T19
#define ZSW_MD5_T19
Definition: md5.hpp:123
websocketpp::versions_supported
static std::vector< int > const versions_supported(helper, helper+4)
Container that stores the list of protocol versions supported.
ZSW_MD5_T38
#define ZSW_MD5_T38
Definition: md5.hpp:142
ZSW_MD5_T13
#define ZSW_MD5_T13
Definition: md5.hpp:117
ZSW_MD5_G
#define ZSW_MD5_G(x, y, z)
ZSW_MD5_T1
#define ZSW_MD5_T1
Definition: md5.hpp:105
ZSW_MD5_I
#define ZSW_MD5_I(x, y, z)
ZSW_MD5_ROTATE_LEFT
#define ZSW_MD5_ROTATE_LEFT(x, n)
ZSW_MD5_T31
#define ZSW_MD5_T31
Definition: md5.hpp:135
ZSW_MD5_T43
#define ZSW_MD5_T43
Definition: md5.hpp:147
ZSW_MD5_T20
#define ZSW_MD5_T20
Definition: md5.hpp:124
ZSW_MD5_T6
#define ZSW_MD5_T6
Definition: md5.hpp:110
ZSW_MD5_T48
#define ZSW_MD5_T48
Definition: md5.hpp:152
ZSW_MD5_T53
#define ZSW_MD5_T53
Definition: md5.hpp:157
ZSW_MD5_T51
#define ZSW_MD5_T51
Definition: md5.hpp:155
ZSW_MD5_T24
#define ZSW_MD5_T24
Definition: md5.hpp:128
ZSW_MD5_T47
#define ZSW_MD5_T47
Definition: md5.hpp:151
ZSW_MD5_T4
#define ZSW_MD5_T4
Definition: md5.hpp:108
ZSW_MD5_T57
#define ZSW_MD5_T57
Definition: md5.hpp:161
ZSW_MD5_T56
#define ZSW_MD5_T56
Definition: md5.hpp:160
ZSW_MD5_T3
#define ZSW_MD5_T3
Definition: md5.hpp:107
ZSW_MD5_T26
#define ZSW_MD5_T26
Definition: md5.hpp:130
ZSW_MD5_T44
#define ZSW_MD5_T44
Definition: md5.hpp:148
ZSW_MD5_T34
#define ZSW_MD5_T34
Definition: md5.hpp:138
ZSW_MD5_T16
#define ZSW_MD5_T16
Definition: md5.hpp:120
ZSW_MD5_T23
#define ZSW_MD5_T23
Definition: md5.hpp:127
ZSW_MD5_BYTE_ORDER
#define ZSW_MD5_BYTE_ORDER
Definition: md5.hpp:101
ZSW_MD5_T14
#define ZSW_MD5_T14
Definition: md5.hpp:118
ZSW_MD5_T_MASK
#define ZSW_MD5_T_MASK
Definition: md5.hpp:104
ZSW_MD5_T25
#define ZSW_MD5_T25
Definition: md5.hpp:129
ZSW_MD5_T60
#define ZSW_MD5_T60
Definition: md5.hpp:164
ZSW_MD5_T9
#define ZSW_MD5_T9
Definition: md5.hpp:113
ZSW_MD5_T30
#define ZSW_MD5_T30
Definition: md5.hpp:134
ZSW_MD5_T58
#define ZSW_MD5_T58
Definition: md5.hpp:162
ZSW_MD5_T33
#define ZSW_MD5_T33
Definition: md5.hpp:137
ZSW_MD5_H
#define ZSW_MD5_H(x, y, z)
ZSW_MD5_T46
#define ZSW_MD5_T46
Definition: md5.hpp:150
ZSW_MD5_T37
#define ZSW_MD5_T37
Definition: md5.hpp:141
websocketpp::md5::md5_state_s
Definition: md5.hpp:82
ZSW_MD5_T64
#define ZSW_MD5_T64
Definition: md5.hpp:168
ZSW_MD5_T17
#define ZSW_MD5_T17
Definition: md5.hpp:121
ZSW_MD5_T10
#define ZSW_MD5_T10
Definition: md5.hpp:114
ZSW_MD5_T12
#define ZSW_MD5_T12
Definition: md5.hpp:116
ZSW_MD5_T18
#define ZSW_MD5_T18
Definition: md5.hpp:122
ZSW_MD5_T36
#define ZSW_MD5_T36
Definition: md5.hpp:140
ZSW_MD5_F
#define ZSW_MD5_F(x, y, z)
ZSW_MD5_T45
#define ZSW_MD5_T45
Definition: md5.hpp:149