summaryrefslogtreecommitdiff
path: root/src/md5.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/md5.cpp')
-rw-r--r--src/md5.cpp323
1 files changed, 183 insertions, 140 deletions
diff --git a/src/md5.cpp b/src/md5.cpp
index f971f23..71f17a0 100644
--- a/src/md5.cpp
+++ b/src/md5.cpp
@@ -11,31 +11,11 @@
11#include "bu/md5.h" 11#include "bu/md5.h"
12#include "bu/stream.h" 12#include "bu/stream.h"
13 13
14 14#ifdef SYSTEM_BIG_ENDIAN
15// This performs a wrapping bitwise shift, kinda' fun! 15# define toLittleEndian( a, b ) _toLittleEndian( a, b )
16 16#else
17#define bit_roll( num, cnt ) \ 17# define toLittleEndian( a, b ) (void)0
18 (((num) << (cnt)) | (((num) >> (32 - (cnt))) & ~(-1<<(cnt)))) 18#endif
19
20//#define md5_cmn( q, a, b, x, s, t ) (bit_roll((a + q + x + t), s) + b)
21
22// The following are handy wrappers for the cmn function
23#define md5_ff( a, b, c, d, x, s, t ) \
24 (md5_cmn((b & c) | ((~b) & d), a, b, x, s, t))
25
26#define md5_gg( a, b, c, d, x, s, t ) \
27 (md5_cmn((b & d) | (c & (~d)), a, b, x, s, t))
28
29#define md5_hh( a, b, c, d, x, s, t ) \
30 (md5_cmn(b ^ c ^ d, a, b, x, s, t))
31
32#define md5_ii( a, b, c, d, x, s, t ) \
33 (md5_cmn(c ^ (b | (~d)), a, b, x, s, t))
34
35inline long md5_cmn( long q, long a, long b, long x, long s, long t )
36{
37 return bit_roll((a + q + x + t), s) + b;
38}
39 19
40Bu::Md5::Md5() 20Bu::Md5::Md5()
41{ 21{
@@ -50,14 +30,13 @@ void Bu::Md5::reset()
50{ 30{
51 // These are the magic seed numbers... 31 // These are the magic seed numbers...
52 32
53 sum[0] = 1732584193; 33 sum[0] = 0x67452301U;
54 sum[1] = -271733879; 34 sum[1] = 0xEFCDAB89U;
55 sum[2] = -1732584194; 35 sum[2] = 0x98BADCFEU;
56 sum[3] = 271733878; 36 sum[3] = 0x10325476U;
57 37
58 iBytes = 0; 38 uBits[0] = 0;
59 memset( inbuf, 0, 4*16 ); 39 uBits[1] = 0;
60 iFill = 0;
61} 40}
62 41
63void Bu::Md5::setSalt( const Bu::String & /*sSalt*/ ) 42void Bu::Md5::setSalt( const Bu::String & /*sSalt*/ )
@@ -67,137 +46,201 @@ void Bu::Md5::setSalt( const Bu::String & /*sSalt*/ )
67void Bu::Md5::addData( const void *sVData, int iSize ) 46void Bu::Md5::addData( const void *sVData, int iSize )
68{ 47{
69 const char *sData = (const char *)sVData; 48 const char *sData = (const char *)sVData;
49 uint32_t t;
50
51 t = uBits[0];
52 if( (uBits[0] = t + ((uint32_t)iSize << 3)) < t )
53 uBits[1]++;
54 uBits[1] += iSize >> 29;
70 55
71 int iInPos = 0; 56 t = (t >> 3) & 0x3f; /* How many bytes we have buffered */
72 for(;;) 57
58 /* Handle any leading odd-sized chunks */
59 if( t )
73 { 60 {
74 for( ; iFill < 16*4 && iInPos < iSize; iFill++, iInPos++ ) 61 unsigned char *p = (unsigned char *) inbuf + t;
75 { 62
76 inbuf[iFill>>2] |= ((long)sData[iInPos]) << ((iFill*8)%32); 63 t = 64 - t;
64 if( iSize < t ) {
65 memcpy( p, sData, iSize );
66 return;
77 } 67 }
78 if( iFill < 16*4 ) 68 memcpy( p, sData, t );
79 break; 69 toLittleEndian( inbuf, 16 );
80 compBlock( inbuf, sum ); 70 compBlock( sum, (uint32_t *)inbuf );
81 memset( inbuf, 0, 4*16 ); 71 sData += t;
82 iFill = 0; 72 iSize -= t;
83 } 73 }
84 iBytes += iSize; 74
75 /* Process data in 64-byte chunks */
76 while( iSize >= 64 )
77 {
78 memcpy( inbuf, sData, 64 );
79 toLittleEndian( inbuf, 16 );
80 compBlock( sum, (uint32_t *)inbuf );
81 sData += 64;
82 iSize -= 64;
83 }
84
85 /* Handle any remaining bytes of data. */
86 memcpy( inbuf, sData, iSize );
85} 87}
86 88
87Bu::String Bu::Md5::getResult() 89Bu::String Bu::Md5::getResult()
88{ 90{
89 long lsum[4]; 91 uint32_t lsum[4];
90 compCap( lsum ); 92 compCap( lsum );
91 return Bu::String( (const char *)lsum, 4*4 ); 93 return Bu::String( (const char *)lsum, 4*4 );
92} 94}
93 95
94void Bu::Md5::writeResult( Bu::Stream &sOut ) 96void Bu::Md5::writeResult( Bu::Stream &sOut )
95{ 97{
96 long lsum[4]; 98 uint32_t lsum[4];
97 compCap( lsum ); 99 compCap( lsum );
98 sOut.write( lsum, 4*4 ); 100 sOut.write( lsum, 4*4 );
99} 101}
100 102
101void Bu::Md5::compCap( long *sumout ) 103void Bu::Md5::compCap( uint32_t *sumout )
102{ 104{
105 uint8_t tmpbuf[64];
103 memcpy( sumout, sum, 4*4 ); 106 memcpy( sumout, sum, 4*4 );
104 long lbuf[16]; 107 memcpy( tmpbuf, inbuf, 64 );
105 memcpy( lbuf, inbuf, 4*16 ); 108
106 109 uint32_t count;
107 lbuf[iFill>>2] |= 0x80 << ((iFill*8)%32); 110 uint8_t *p;
108 uint64_t iBits = iBytes*8; 111
109 if( iBytes > 0 && iFill>>2 >= 14 ) 112 /* Compute number of bytes mod 64 */
110 { 113 count = (uBits[0] >> 3) & 0x3F;
111 compBlock( lbuf, sumout ); 114
112 memset( lbuf, 0, 4*16 ); 115 /* Set the first char of padding to 0x80. This is safe since there is
113 memcpy( lbuf+14, &iBits, 8 ); 116 always at least one byte free */
114 compBlock( lbuf, sumout ); 117 p = tmpbuf + count;
115 } 118 *p++ = 0x80;
116 else 119
117 { 120 /* Bytes of padding needed to make 64 bytes */
118 memcpy( lbuf+14, &iBits, 8 ); 121 count = 64 - 1 - count;
119 compBlock( lbuf, sumout ); 122
123 /* Pad out to 56 mod 64 */
124 if (count < 8) {
125 /* Two lots of padding: Pad the first block to 64 bytes */
126 memset( p, 0, count );
127 toLittleEndian( tmpbuf, 16 );
128 compBlock( sumout, (uint32_t *)tmpbuf );
129
130 /* Now fill the next block with 56 bytes */
131 memset( tmpbuf, 0, 56);
132 } else {
133 /* Pad block to 56 bytes */
134 memset( p, 0, count - 8);
120 } 135 }
136 toLittleEndian( tmpbuf, 14 );
137
138 /* Append length in bits and transform */
139 ((uint32_t *) tmpbuf)[14] = uBits[0];
140 ((uint32_t *) tmpbuf)[15] = uBits[1];
141
142 compBlock( sumout, (uint32_t *)tmpbuf );
143 toLittleEndian((unsigned char *)sumout, 4);
121} 144}
122 145
123void Bu::Md5::compBlock( long *x, long *lsum ) 146#define F1(x, y, z) (z ^ (x & (y ^ z)))
147#define F2(x, y, z) F1(z, x, y)
148#define F3(x, y, z) (x ^ y ^ z)
149#define F4(x, y, z) (y ^ (x | ~z))
150
151/* This is the central step in the MD5 algorithm. */
152#define MD5STEP(f, w, x, y, z, data, s) \
153 ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
154
155void Bu::Md5::compBlock( uint32_t *lsum, uint32_t *x )
124{ 156{
125 long a = lsum[0]; 157 register uint32_t a, b, c, d;
126 long b = lsum[1]; 158 a = lsum[0];
127 long c = lsum[2]; 159 b = lsum[1];
128 long d = lsum[3]; 160 c = lsum[2];
129 161 d = lsum[3];
130 a = md5_ff(a, b, c, d, x[ 0], 7 , -680876936); 162
131 d = md5_ff(d, a, b, c, x[ 1], 12, -389564586); 163 MD5STEP(F1, a, b, c, d, x[0] + 0xd76aa478, 7);
132 c = md5_ff(c, d, a, b, x[ 2], 17, 606105819); 164 MD5STEP(F1, d, a, b, c, x[1] + 0xe8c7b756, 12);
133 b = md5_ff(b, c, d, a, x[ 3], 22, -1044525330); 165 MD5STEP(F1, c, d, a, b, x[2] + 0x242070db, 17);
134 a = md5_ff(a, b, c, d, x[ 4], 7 , -176418897); 166 MD5STEP(F1, b, c, d, a, x[3] + 0xc1bdceee, 22);
135 d = md5_ff(d, a, b, c, x[ 5], 12, 1200080426); 167 MD5STEP(F1, a, b, c, d, x[4] + 0xf57c0faf, 7);
136 c = md5_ff(c, d, a, b, x[ 6], 17, -1473231341); 168 MD5STEP(F1, d, a, b, c, x[5] + 0x4787c62a, 12);
137 b = md5_ff(b, c, d, a, x[ 7], 22, -45705983); 169 MD5STEP(F1, c, d, a, b, x[6] + 0xa8304613, 17);
138 a = md5_ff(a, b, c, d, x[ 8], 7 , 1770035416); 170 MD5STEP(F1, b, c, d, a, x[7] + 0xfd469501, 22);
139 d = md5_ff(d, a, b, c, x[ 9], 12, -1958414417); 171 MD5STEP(F1, a, b, c, d, x[8] + 0x698098d8, 7);
140 c = md5_ff(c, d, a, b, x[10], 17, -42063); 172 MD5STEP(F1, d, a, b, c, x[9] + 0x8b44f7af, 12);
141 b = md5_ff(b, c, d, a, x[11], 22, -1990404162); 173 MD5STEP(F1, c, d, a, b, x[10] + 0xffff5bb1, 17);
142 a = md5_ff(a, b, c, d, x[12], 7 , 1804603682); 174 MD5STEP(F1, b, c, d, a, x[11] + 0x895cd7be, 22);
143 d = md5_ff(d, a, b, c, x[13], 12, -40341101); 175 MD5STEP(F1, a, b, c, d, x[12] + 0x6b901122, 7);
144 c = md5_ff(c, d, a, b, x[14], 17, -1502002290); 176 MD5STEP(F1, d, a, b, c, x[13] + 0xfd987193, 12);
145 b = md5_ff(b, c, d, a, x[15], 22, 1236535329); 177 MD5STEP(F1, c, d, a, b, x[14] + 0xa679438e, 17);
146 178 MD5STEP(F1, b, c, d, a, x[15] + 0x49b40821, 22);
147 a = md5_gg(a, b, c, d, x[ 1], 5 , -165796510); 179
148 d = md5_gg(d, a, b, c, x[ 6], 9 , -1069501632); 180 MD5STEP(F2, a, b, c, d, x[1] + 0xf61e2562, 5);
149 c = md5_gg(c, d, a, b, x[11], 14, 643717713); 181 MD5STEP(F2, d, a, b, c, x[6] + 0xc040b340, 9);
150 b = md5_gg(b, c, d, a, x[ 0], 20, -373897302); 182 MD5STEP(F2, c, d, a, b, x[11] + 0x265e5a51, 14);
151 a = md5_gg(a, b, c, d, x[ 5], 5 , -701558691); 183 MD5STEP(F2, b, c, d, a, x[0] + 0xe9b6c7aa, 20);
152 d = md5_gg(d, a, b, c, x[10], 9 , 38016083); 184 MD5STEP(F2, a, b, c, d, x[5] + 0xd62f105d, 5);
153 c = md5_gg(c, d, a, b, x[15], 14, -660478335); 185 MD5STEP(F2, d, a, b, c, x[10] + 0x02441453, 9);
154 b = md5_gg(b, c, d, a, x[ 4], 20, -405537848); 186 MD5STEP(F2, c, d, a, b, x[15] + 0xd8a1e681, 14);
155 a = md5_gg(a, b, c, d, x[ 9], 5 , 568446438); 187 MD5STEP(F2, b, c, d, a, x[4] + 0xe7d3fbc8, 20);
156 d = md5_gg(d, a, b, c, x[14], 9 , -1019803690); 188 MD5STEP(F2, a, b, c, d, x[9] + 0x21e1cde6, 5);
157 c = md5_gg(c, d, a, b, x[ 3], 14, -187363961); 189 MD5STEP(F2, d, a, b, c, x[14] + 0xc33707d6, 9);
158 b = md5_gg(b, c, d, a, x[ 8], 20, 1163531501); 190 MD5STEP(F2, c, d, a, b, x[3] + 0xf4d50d87, 14);
159 a = md5_gg(a, b, c, d, x[13], 5 , -1444681467); 191 MD5STEP(F2, b, c, d, a, x[8] + 0x455a14ed, 20);
160 d = md5_gg(d, a, b, c, x[ 2], 9 , -51403784); 192 MD5STEP(F2, a, b, c, d, x[13] + 0xa9e3e905, 5);
161 c = md5_gg(c, d, a, b, x[ 7], 14, 1735328473); 193 MD5STEP(F2, d, a, b, c, x[2] + 0xfcefa3f8, 9);
162 b = md5_gg(b, c, d, a, x[12], 20, -1926607734); 194 MD5STEP(F2, c, d, a, b, x[7] + 0x676f02d9, 14);
163 195 MD5STEP(F2, b, c, d, a, x[12] + 0x8d2a4c8a, 20);
164 a = md5_hh(a, b, c, d, x[ 5], 4 , -378558); 196
165 d = md5_hh(d, a, b, c, x[ 8], 11, -2022574463); 197 MD5STEP(F3, a, b, c, d, x[5] + 0xfffa3942, 4);
166 c = md5_hh(c, d, a, b, x[11], 16, 1839030562); 198 MD5STEP(F3, d, a, b, c, x[8] + 0x8771f681, 11);
167 b = md5_hh(b, c, d, a, x[14], 23, -35309556); 199 MD5STEP(F3, c, d, a, b, x[11] + 0x6d9d6122, 16);
168 a = md5_hh(a, b, c, d, x[ 1], 4 , -1530992060); 200 MD5STEP(F3, b, c, d, a, x[14] + 0xfde5380c, 23);
169 d = md5_hh(d, a, b, c, x[ 4], 11, 1272893353); 201 MD5STEP(F3, a, b, c, d, x[1] + 0xa4beea44, 4);
170 c = md5_hh(c, d, a, b, x[ 7], 16, -155497632); 202 MD5STEP(F3, d, a, b, c, x[4] + 0x4bdecfa9, 11);
171 b = md5_hh(b, c, d, a, x[10], 23, -1094730640); 203 MD5STEP(F3, c, d, a, b, x[7] + 0xf6bb4b60, 16);
172 a = md5_hh(a, b, c, d, x[13], 4 , 681279174); 204 MD5STEP(F3, b, c, d, a, x[10] + 0xbebfbc70, 23);
173 d = md5_hh(d, a, b, c, x[ 0], 11, -358537222); 205 MD5STEP(F3, a, b, c, d, x[13] + 0x289b7ec6, 4);
174 c = md5_hh(c, d, a, b, x[ 3], 16, -722521979); 206 MD5STEP(F3, d, a, b, c, x[0] + 0xeaa127fa, 11);
175 b = md5_hh(b, c, d, a, x[ 6], 23, 76029189); 207 MD5STEP(F3, c, d, a, b, x[3] + 0xd4ef3085, 16);
176 a = md5_hh(a, b, c, d, x[ 9], 4 , -640364487); 208 MD5STEP(F3, b, c, d, a, x[6] + 0x04881d05, 23);
177 d = md5_hh(d, a, b, c, x[12], 11, -421815835); 209 MD5STEP(F3, a, b, c, d, x[9] + 0xd9d4d039, 4);
178 c = md5_hh(c, d, a, b, x[15], 16, 530742520); 210 MD5STEP(F3, d, a, b, c, x[12] + 0xe6db99e5, 11);
179 b = md5_hh(b, c, d, a, x[ 2], 23, -995338651); 211 MD5STEP(F3, c, d, a, b, x[15] + 0x1fa27cf8, 16);
180 212 MD5STEP(F3, b, c, d, a, x[2] + 0xc4ac5665, 23);
181 a = md5_ii(a, b, c, d, x[ 0], 6 , -198630844); 213
182 d = md5_ii(d, a, b, c, x[ 7], 10, 1126891415); 214 MD5STEP(F4, a, b, c, d, x[0] + 0xf4292244, 6);
183 c = md5_ii(c, d, a, b, x[14], 15, -1416354905); 215 MD5STEP(F4, d, a, b, c, x[7] + 0x432aff97, 10);
184 b = md5_ii(b, c, d, a, x[ 5], 21, -57434055); 216 MD5STEP(F4, c, d, a, b, x[14] + 0xab9423a7, 15);
185 a = md5_ii(a, b, c, d, x[12], 6 , 1700485571); 217 MD5STEP(F4, b, c, d, a, x[5] + 0xfc93a039, 21);
186 d = md5_ii(d, a, b, c, x[ 3], 10, -1894986606); 218 MD5STEP(F4, a, b, c, d, x[12] + 0x655b59c3, 6);
187 c = md5_ii(c, d, a, b, x[10], 15, -1051523); 219 MD5STEP(F4, d, a, b, c, x[3] + 0x8f0ccc92, 10);
188 b = md5_ii(b, c, d, a, x[ 1], 21, -2054922799); 220 MD5STEP(F4, c, d, a, b, x[10] + 0xffeff47d, 15);
189 a = md5_ii(a, b, c, d, x[ 8], 6 , 1873313359); 221 MD5STEP(F4, b, c, d, a, x[1] + 0x85845dd1, 21);
190 d = md5_ii(d, a, b, c, x[15], 10, -30611744); 222 MD5STEP(F4, a, b, c, d, x[8] + 0x6fa87e4f, 6);
191 c = md5_ii(c, d, a, b, x[ 6], 15, -1560198380); 223 MD5STEP(F4, d, a, b, c, x[15] + 0xfe2ce6e0, 10);
192 b = md5_ii(b, c, d, a, x[13], 21, 1309151649); 224 MD5STEP(F4, c, d, a, b, x[6] + 0xa3014314, 15);
193 a = md5_ii(a, b, c, d, x[ 4], 6 , -145523070); 225 MD5STEP(F4, b, c, d, a, x[13] + 0x4e0811a1, 21);
194 d = md5_ii(d, a, b, c, x[11], 10, -1120210379); 226 MD5STEP(F4, a, b, c, d, x[4] + 0xf7537e82, 6);
195 c = md5_ii(c, d, a, b, x[ 2], 15, 718787259); 227 MD5STEP(F4, d, a, b, c, x[11] + 0xbd3af235, 10);
196 b = md5_ii(b, c, d, a, x[ 9], 21, -343485551); 228 MD5STEP(F4, c, d, a, b, x[2] + 0x2ad7d2bb, 15);
197 229 MD5STEP(F4, b, c, d, a, x[9] + 0xeb86d391, 21);
198 lsum[0] = a + lsum[0]; 230
199 lsum[1] = b + lsum[1]; 231 lsum[0] += a;
200 lsum[2] = c + lsum[2]; 232 lsum[1] += b;
201 lsum[3] = d + lsum[3]; 233 lsum[2] += c;
234 lsum[3] += d;
202} 235}
203 236
237void Bu::Md5::_toLittleEndian( uint8_t *buf, uint32_t count )
238{
239 uint32_t t;
240 do {
241 t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
242 ((unsigned) buf[1] << 8 | buf[0]);
243 *(uint32_t *) buf = t;
244 buf += 4;
245 } while( --count );
246}