Add mangling code
[hashcat.git] / OpenCL / mangle.cl
1 // Domain to use for mangling
2 __constant u8 domain[] = "flypig.co.uk";
3 __constant u32x domain_len = 12;
4
5 // Characters used for base64 encoding
6 __constant char b64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
7
8 // Perform an MD5 transform step
9 // Should be called through hmac_md5_pad_mangle and hmac_md5_run_mangle
10 void md5_transform_mangle (const u32x w0[4], const u32x w1[4], const u32x w2[4], const u32x w3[4], u32x digest[4])
11 {
12   u32x a = digest[0];
13   u32x b = digest[1];
14   u32x c = digest[2];
15   u32x d = digest[3];
16
17   u32x w0_t = w0[0];
18   u32x w1_t = w0[1];
19   u32x w2_t = w0[2];
20   u32x w3_t = w0[3];
21   u32x w4_t = w1[0];
22   u32x w5_t = w1[1];
23   u32x w6_t = w1[2];
24   u32x w7_t = w1[3];
25   u32x w8_t = w2[0];
26   u32x w9_t = w2[1];
27   u32x wa_t = w2[2];
28   u32x wb_t = w2[3];
29   u32x wc_t = w3[0];
30   u32x wd_t = w3[1];
31   u32x we_t = w3[2];
32   u32x wf_t = w3[3];
33
34   MD5_STEP (MD5_Fo, a, b, c, d, w0_t, MD5C00, MD5S00);
35   MD5_STEP (MD5_Fo, d, a, b, c, w1_t, MD5C01, MD5S01);
36   MD5_STEP (MD5_Fo, c, d, a, b, w2_t, MD5C02, MD5S02);
37   MD5_STEP (MD5_Fo, b, c, d, a, w3_t, MD5C03, MD5S03);
38   MD5_STEP (MD5_Fo, a, b, c, d, w4_t, MD5C04, MD5S00);
39   MD5_STEP (MD5_Fo, d, a, b, c, w5_t, MD5C05, MD5S01);
40   MD5_STEP (MD5_Fo, c, d, a, b, w6_t, MD5C06, MD5S02);
41   MD5_STEP (MD5_Fo, b, c, d, a, w7_t, MD5C07, MD5S03);
42   MD5_STEP (MD5_Fo, a, b, c, d, w8_t, MD5C08, MD5S00);
43   MD5_STEP (MD5_Fo, d, a, b, c, w9_t, MD5C09, MD5S01);
44   MD5_STEP (MD5_Fo, c, d, a, b, wa_t, MD5C0a, MD5S02);
45   MD5_STEP (MD5_Fo, b, c, d, a, wb_t, MD5C0b, MD5S03);
46   MD5_STEP (MD5_Fo, a, b, c, d, wc_t, MD5C0c, MD5S00);
47   MD5_STEP (MD5_Fo, d, a, b, c, wd_t, MD5C0d, MD5S01);
48   MD5_STEP (MD5_Fo, c, d, a, b, we_t, MD5C0e, MD5S02);
49   MD5_STEP (MD5_Fo, b, c, d, a, wf_t, MD5C0f, MD5S03);
50
51   MD5_STEP (MD5_Go, a, b, c, d, w1_t, MD5C10, MD5S10);
52   MD5_STEP (MD5_Go, d, a, b, c, w6_t, MD5C11, MD5S11);
53   MD5_STEP (MD5_Go, c, d, a, b, wb_t, MD5C12, MD5S12);
54   MD5_STEP (MD5_Go, b, c, d, a, w0_t, MD5C13, MD5S13);
55   MD5_STEP (MD5_Go, a, b, c, d, w5_t, MD5C14, MD5S10);
56   MD5_STEP (MD5_Go, d, a, b, c, wa_t, MD5C15, MD5S11);
57   MD5_STEP (MD5_Go, c, d, a, b, wf_t, MD5C16, MD5S12);
58   MD5_STEP (MD5_Go, b, c, d, a, w4_t, MD5C17, MD5S13);
59   MD5_STEP (MD5_Go, a, b, c, d, w9_t, MD5C18, MD5S10);
60   MD5_STEP (MD5_Go, d, a, b, c, we_t, MD5C19, MD5S11);
61   MD5_STEP (MD5_Go, c, d, a, b, w3_t, MD5C1a, MD5S12);
62   MD5_STEP (MD5_Go, b, c, d, a, w8_t, MD5C1b, MD5S13);
63   MD5_STEP (MD5_Go, a, b, c, d, wd_t, MD5C1c, MD5S10);
64   MD5_STEP (MD5_Go, d, a, b, c, w2_t, MD5C1d, MD5S11);
65   MD5_STEP (MD5_Go, c, d, a, b, w7_t, MD5C1e, MD5S12);
66   MD5_STEP (MD5_Go, b, c, d, a, wc_t, MD5C1f, MD5S13);
67
68   MD5_STEP (MD5_H, a, b, c, d, w5_t, MD5C20, MD5S20);
69   MD5_STEP (MD5_H, d, a, b, c, w8_t, MD5C21, MD5S21);
70   MD5_STEP (MD5_H, c, d, a, b, wb_t, MD5C22, MD5S22);
71   MD5_STEP (MD5_H, b, c, d, a, we_t, MD5C23, MD5S23);
72   MD5_STEP (MD5_H, a, b, c, d, w1_t, MD5C24, MD5S20);
73   MD5_STEP (MD5_H, d, a, b, c, w4_t, MD5C25, MD5S21);
74   MD5_STEP (MD5_H, c, d, a, b, w7_t, MD5C26, MD5S22);
75   MD5_STEP (MD5_H, b, c, d, a, wa_t, MD5C27, MD5S23);
76   MD5_STEP (MD5_H, a, b, c, d, wd_t, MD5C28, MD5S20);
77   MD5_STEP (MD5_H, d, a, b, c, w0_t, MD5C29, MD5S21);
78   MD5_STEP (MD5_H, c, d, a, b, w3_t, MD5C2a, MD5S22);
79   MD5_STEP (MD5_H, b, c, d, a, w6_t, MD5C2b, MD5S23);
80   MD5_STEP (MD5_H, a, b, c, d, w9_t, MD5C2c, MD5S20);
81   MD5_STEP (MD5_H, d, a, b, c, wc_t, MD5C2d, MD5S21);
82   MD5_STEP (MD5_H, c, d, a, b, wf_t, MD5C2e, MD5S22);
83   MD5_STEP (MD5_H, b, c, d, a, w2_t, MD5C2f, MD5S23);
84
85   MD5_STEP (MD5_I, a, b, c, d, w0_t, MD5C30, MD5S30);
86   MD5_STEP (MD5_I, d, a, b, c, w7_t, MD5C31, MD5S31);
87   MD5_STEP (MD5_I, c, d, a, b, we_t, MD5C32, MD5S32);
88   MD5_STEP (MD5_I, b, c, d, a, w5_t, MD5C33, MD5S33);
89   MD5_STEP (MD5_I, a, b, c, d, wc_t, MD5C34, MD5S30);
90   MD5_STEP (MD5_I, d, a, b, c, w3_t, MD5C35, MD5S31);
91   MD5_STEP (MD5_I, c, d, a, b, wa_t, MD5C36, MD5S32);
92   MD5_STEP (MD5_I, b, c, d, a, w1_t, MD5C37, MD5S33);
93   MD5_STEP (MD5_I, a, b, c, d, w8_t, MD5C38, MD5S30);
94   MD5_STEP (MD5_I, d, a, b, c, wf_t, MD5C39, MD5S31);
95   MD5_STEP (MD5_I, c, d, a, b, w6_t, MD5C3a, MD5S32);
96   MD5_STEP (MD5_I, b, c, d, a, wd_t, MD5C3b, MD5S33);
97   MD5_STEP (MD5_I, a, b, c, d, w4_t, MD5C3c, MD5S30);
98   MD5_STEP (MD5_I, d, a, b, c, wb_t, MD5C3d, MD5S31);
99   MD5_STEP (MD5_I, c, d, a, b, w2_t, MD5C3e, MD5S32);
100   MD5_STEP (MD5_I, b, c, d, a, w9_t, MD5C3f, MD5S33);
101
102   digest[0] += a;
103   digest[1] += b;
104   digest[2] += c;
105   digest[3] += d;
106 }
107
108 // Set up the HMAC-MD5 process
109 // The ipad and opad arrays can be retained to run multiple HMAC-MD5 processes
110 // without having to recalculate
111 // w0, w1, w2, w3 - contain up to 64 bytes of the HMAC key
112 // ipad, opad - contain the returned data to pass into the next call
113 void hmac_md5_pad_mangle (u32x w0[4], u32x w1[4], u32x w2[4], u32x w3[4], u32x ipad[4], u32x opad[4])
114 {
115   w0[0] = w0[0] ^ 0x36363636;
116   w0[1] = w0[1] ^ 0x36363636;
117   w0[2] = w0[2] ^ 0x36363636;
118   w0[3] = w0[3] ^ 0x36363636;
119   w1[0] = w1[0] ^ 0x36363636;
120   w1[1] = w1[1] ^ 0x36363636;
121   w1[2] = w1[2] ^ 0x36363636;
122   w1[3] = w1[3] ^ 0x36363636;
123   w2[0] = w2[0] ^ 0x36363636;
124   w2[1] = w2[1] ^ 0x36363636;
125   w2[2] = w2[2] ^ 0x36363636;
126   w2[3] = w2[3] ^ 0x36363636;
127   w3[0] = w3[0] ^ 0x36363636;
128   w3[1] = w3[1] ^ 0x36363636;
129   w3[2] = w3[2] ^ 0x36363636;
130   w3[3] = w3[3] ^ 0x36363636;
131
132   ipad[0] = MD5M_A;
133   ipad[1] = MD5M_B;
134   ipad[2] = MD5M_C;
135   ipad[3] = MD5M_D;
136
137   md5_transform_mangle (w0, w1, w2, w3, ipad);
138
139   w0[0] = w0[0] ^ 0x6a6a6a6a;
140   w0[1] = w0[1] ^ 0x6a6a6a6a;
141   w0[2] = w0[2] ^ 0x6a6a6a6a;
142   w0[3] = w0[3] ^ 0x6a6a6a6a;
143   w1[0] = w1[0] ^ 0x6a6a6a6a;
144   w1[1] = w1[1] ^ 0x6a6a6a6a;
145   w1[2] = w1[2] ^ 0x6a6a6a6a;
146   w1[3] = w1[3] ^ 0x6a6a6a6a;
147   w2[0] = w2[0] ^ 0x6a6a6a6a;
148   w2[1] = w2[1] ^ 0x6a6a6a6a;
149   w2[2] = w2[2] ^ 0x6a6a6a6a;
150   w2[3] = w2[3] ^ 0x6a6a6a6a;
151   w3[0] = w3[0] ^ 0x6a6a6a6a;
152   w3[1] = w3[1] ^ 0x6a6a6a6a;
153   w3[2] = w3[2] ^ 0x6a6a6a6a;
154   w3[3] = w3[3] ^ 0x6a6a6a6a;
155
156   opad[0] = MD5M_A;
157   opad[1] = MD5M_B;
158   opad[2] = MD5M_C;
159   opad[3] = MD5M_D;
160
161   md5_transform_mangle (w0, w1, w2, w3, opad);
162 }
163
164 // Continue the HMAC-MD5 process
165 // It's up to the caller to add the final length and padding terminators
166 // hmac_md5_pad_mangle call, which can be used across multiple HMACs
167 // w0, w1, w2, w3 - contain up to 64 bytes of data to HMAC
168 // ipad, opad - should contain the output from the 
169 // digest - the 16-byte result of the HMAC
170 void hmac_md5_run_mangle (u32x w0[4], u32x w1[4], u32x w2[4], u32x w3[4], u32x ipad[4], u32x opad[4], u32x digest[4])
171 {
172   digest[0] = ipad[0];
173   digest[1] = ipad[1];
174   digest[2] = ipad[2];
175   digest[3] = ipad[3];
176
177   md5_transform_mangle (w0, w1, w2, w3, digest);
178
179   w0[0] = digest[0];
180   w0[1] = digest[1];
181   w0[2] = digest[2];
182   w0[3] = digest[3];
183   w1[0] = 0x80;
184   w1[1] = 0;
185   w1[2] = 0;
186   w1[3] = 0;
187   w2[0] = 0;
188   w2[1] = 0;
189   w2[2] = 0;
190   w2[3] = 0;
191   w3[0] = 0;
192   w3[1] = 0;
193   w3[2] = (64 + 16) * 8;
194   w3[3] = 0;
195
196   digest[0] = opad[0];
197   digest[1] = opad[1];
198   digest[2] = opad[2];
199   digest[3] = opad[3];
200
201   md5_transform_mangle (w0, w1, w2, w3, digest);
202 }
203
204 // Perfrom an HMAC-MD5 with the given key and using the domain constant as the
205 // data to HMAC
206 // in_key - the key to use (the user's password)
207 // key-len - the length of the key in bytes
208 // out_digest - returns the 16 byte result
209 void md5hmac_domain_mangle (u8 const *const in_key, const u32x key_len, u8 out_digest[16])
210 {
211   u32 pos;
212
213   // Data
214   u32x data_buf[16];
215
216   for (pos = 0; pos < domain_len; pos++)
217   {
218     ((u8 *) data_buf)[pos] = domain[pos];
219   }
220   for (pos = domain_len; pos < 64; pos++)
221   {
222     ((u8 *) data_buf)[pos] = 0;
223   }
224
225   // Key
226   u32x key_buf[16];
227
228   for (pos = 0; pos < key_len; pos++)
229   {
230     ((u8 *) key_buf)[pos] = in_key[pos];
231   }
232   for (pos = key_len; pos < 64; pos++)
233   {
234     ((u8 *) key_buf)[pos] = 0;
235   }
236
237   // Pads
238   u32x ipad[4];
239   u32x opad[4];
240
241   hmac_md5_pad_mangle (key_buf, key_buf + 4, key_buf + 8, key_buf + 12, ipad, opad);
242
243   // Loop (except this time we don't actually loop)
244   append_0x80_2x4_VV (data_buf, data_buf + 4, domain_len);
245
246   data_buf[14] = (64 + domain_len) * 8;
247
248   hmac_md5_run_mangle (data_buf, data_buf + 4, data_buf + 8, data_buf + 12, ipad, opad, (u32x *) out_digest);
249 }
250
251 // Base64 encode a string
252 // base64_hash - the returned hahs
253 // len - the length of the input string
254 // base64_plain - the string to encode
255 // returns the length of the final encoding
256 u32 b64_encode_mangle (u8 * base64_hash, const u32 len, const u8 * base64_plain)
257 {
258   u8 *out_ptr = (u8 *) base64_hash;
259   u8 *in_ptr = (u8 *) base64_plain;
260   u32 out_len;
261
262   u32 i;
263
264   // Encode the easy iniitial characters
265   out_len = 0;
266   for (i = 0; i < (len - 2); i += 3)
267   {
268     char out_val0 = b64_table[((in_ptr[0] >> 2) & 0x3f)];
269     char out_val1 = b64_table[((in_ptr[0] << 4) & 0x30) | ((in_ptr[1] >> 4) & 0x0f)];
270     char out_val2 = b64_table[((in_ptr[1] << 2) & 0x3c) | ((in_ptr[2] >> 6) & 0x03)];
271     char out_val3 = b64_table[((in_ptr[2] >> 0) & 0x3f)];
272
273     out_ptr[0] = out_val0 & 0x7f;
274     out_ptr[1] = out_val1 & 0x7f;
275     out_ptr[2] = out_val2 & 0x7f;
276     out_ptr[3] = out_val3 & 0x7f;
277
278     in_ptr += 3;
279     out_ptr += 4;
280     out_len += 4;
281   }
282   // Deal with the awkward terminating characters if there are any
283   if (i == (len - 1))
284   {
285     // Input string has one hanging character
286     char out_val0 = b64_table[((in_ptr[0] >> 2) & 0x3f)];
287     char out_val1 = b64_table[((in_ptr[0] << 4) & 0x30)];
288
289     out_ptr[0] = out_val0 & 0x7f;
290     out_ptr[1] = out_val1 & 0x7f;
291     out_ptr[2] = '=';
292     out_ptr[3] = '=';
293
294     in_ptr += 3;
295     out_ptr += 4;
296     out_len += 4;
297   }
298   if (i == (len - 2))
299   {
300     // Input string has two hanging characters
301     char out_val0 = b64_table[((in_ptr[0] >> 2) & 0x3f)];
302     char out_val1 = b64_table[((in_ptr[0] << 4) & 0x30) | ((in_ptr[1] >> 4) & 0x0f)];
303     char out_val2 = b64_table[((in_ptr[1] << 2) & 0x3c)];
304
305     out_ptr[0] = out_val0 & 0x7f;
306     out_ptr[1] = out_val1 & 0x7f;
307     out_ptr[2] = out_val2 & 0x7f;
308     out_ptr[3] = '=';
309
310     in_ptr += 3;
311     out_ptr += 4;
312     out_len += 4;
313   }
314
315   return out_len;
316 }
317
318 // Determine whether a given string contains non-alphanumeric values
319 // A non-alphanumeric is anything except a-z, A-Z, 0-9
320 // data - the string to check
321 // length - the length of the string
322 // returns true if there's a non-alphanumeric value, false o/w
323 bool containsnonalphanumeric_mangle (u8 * data, u32 length)
324 {
325   bool nonalphanumeric;
326   u32 pos;
327   char check;
328   u32 startingSize;
329
330   nonalphanumeric = false;
331   // Check each character individually
332   for (pos = 0; (pos < length) && !nonalphanumeric; pos++)
333   {
334     check = data[pos];
335     if (!((check >= 'a') && (check <= 'z')) && !((check >= 'A') && (check <= 'Z')) && !((check >= '0') && (check <= '9')) && !(check == '_'))
336     {
337       nonalphanumeric = true;
338     }
339   }
340
341   return nonalphanumeric;
342 }
343
344 // Determine whether a string contains any value between a given range
345 // password - the string to check
346 // length - the length of the string to check
347 // start - the inclusive lower bound of the range to check between
348 // end - the inclusive upper bound of the range to check between
349 // returns true if the string contains a value that falls in the range
350 // returns false o/w
351 bool contains_mangle (u8 const *password, u32 length, u8 start, u8 end)
352 {
353   bool doescontain = false;
354   u32 pos;
355
356   // Check each character individually
357   for (pos = 0; (pos < length) && (doescontain == false); pos++)
358   {
359     if ((password[pos] >= start) && (password[pos] <= end))
360     {
361       doescontain = true;
362     }
363   }
364
365   return doescontain;
366 }
367
368 // Rotate the characters in a string to the left by the given number of
369 // characters
370 // torotate - the string to rotate
371 // length - the length of the string to rotate
372 // steps - the number of steps to rotate to the left by
373 void rotate_string_mangle (u8 * torotate, u32 length, u32 steps)
374 {
375   u8 scratch[64];
376   u32 pos;
377
378   // Create a rotated copy in a temporary buffer
379   for (pos = 0; pos < length; pos++)
380   {
381     scratch[pos] = torotate[(pos + steps) % length];
382   }
383
384   // Copy the result back into the original buffer
385   for (pos = 0; pos < length; pos++)
386   {
387     torotate[pos] = scratch[pos];
388   }
389 }
390
391 // Perform the mangle operation on the string to be hashed
392 // w0, w1 - the string to be mangled
393 // in_len - the length of the string to be mangled
394 u32x mangle (u32x w0[4], u32x w1[4], const u32x in_len)
395 {
396   u32x out_len = in_len;
397
398   u32 digest[4];
399   u32 data[8];
400   u32 hash[8];
401   u32 i;
402   u32 size;
403   u32 extrasize;
404   u32 startingsize;
405   bool nonalphanumeric;
406   u32 extrapos;
407   u8 next;
408
409   hash[0] = w0[0];
410   hash[1] = w0[1];
411   hash[2] = w0[2];
412   hash[3] = w0[3];
413   hash[4] = w1[0];
414   hash[5] = w1[1];
415   hash[6] = w1[2];
416   hash[7] = w1[3];
417
418   // HMAC-MD5 the domain name using the password as the key
419   md5hmac_domain_mangle ((u8 *) hash, in_len, (u8 *) digest);
420
421   // Check whether the original password contains non-alphanumeric values
422   nonalphanumeric = containsnonalphanumeric_mangle ((u8 *) hash, in_len);
423
424   w0[0] = digest[0];
425   w0[1] = digest[1];
426   w0[2] = digest[2];
427   w0[3] = digest[3];
428   w1[0] = 0;
429   w1[1] = 0;
430   w1[2] = 0;
431   w1[3] = 0;
432
433   // Base64 encode the HMAC; this will be what we use to generate the password
434   out_len = b64_encode_mangle ((u8 *) hash, 16, (u8 *) w0);
435
436   out_len = 22;                 // b64 encoding will produce 24 bytes output, but last two will be "=="
437   extrasize = 22;
438   size = in_len + 2;
439
440   // for (i = out_len; i < 32; i++) {
441   // ((u8 *)hash)[i] = 0;
442   // }
443
444   startingsize = size - 4;
445   startingsize = (startingsize < extrasize) ? startingsize : extrasize;
446
447   // Transfer the intial portion for output
448   for (i = 0; i < startingsize; i++)
449   {
450     ((u8 *) data)[i] = ((u8 *) hash)[i];
451   }
452   for (i = startingsize; i < 32; i++)
453   {
454     ((u8 *) data)[i] = 0;
455   }
456
457   extrapos = startingsize;
458
459   // Add the extras
460   // Capital letter
461   next = (extrapos < extrasize) ? ((u8 *) hash)[extrapos] : 0;
462   extrapos++;
463   if (!contains_mangle ((u8 *) data, startingsize, 'A', 'Z'))
464   {
465     next = 'A' + (next % ('Z' - 'A' + 1));
466   }
467   ((u8 *) data)[startingsize] = next;
468   startingsize++;
469
470   // Lower case letter
471   next = (extrapos < extrasize) ? ((u8 *) hash)[extrapos] : 0;
472   extrapos++;
473   if (!contains_mangle ((u8 *) data, startingsize, 'a', 'z'))
474   {
475     next = 'a' + (next % ('z' - 'a' + 1));
476   }
477   ((u8 *) data)[startingsize] = next;
478   startingsize++;
479
480   // Number
481   next = (extrapos < extrasize) ? ((u8 *) hash)[extrapos] : 0;
482   extrapos++;
483   if (!contains_mangle ((u8 *) data, startingsize, '0', '9'))
484   {
485     next = '0' + (next % ('9' - '0' + 1));
486   }
487   ((u8 *) data)[startingsize] = next;
488   startingsize++;
489
490   // Non alphanumeric
491   if (containsnonalphanumeric_mangle ((u8 *) data, startingsize) && nonalphanumeric)
492   {
493     next = (extrapos < extrasize) ? ((u8 *) hash)[extrapos] : 0;
494     extrapos++;
495   }
496   else
497   {
498     next = '+';
499   }
500   ((u8 *) data)[startingsize] = next;
501   startingsize++;
502
503   // If there's no alphanumeric values in the original password
504   // remove them from the result
505   if (!nonalphanumeric)
506   {
507     for (i = 0; i < startingsize; i++)
508     {
509       if (containsnonalphanumeric_mangle (((u8 *) data) + i, 1))
510       {
511         next = (extrapos < extrasize) ? ((u8 *) hash)[extrapos] : 0;
512         extrapos++;
513         next = 'A' + (next % ('Z' - 'A' + 1));
514         ((u8 *) data)[i] = next;
515       }
516     }
517   }
518
519   // Rotate the result to ranomise where the non-alphanumerics are
520   next = (extrapos < extrasize) ? ((u8 *) hash)[extrapos] : 0;
521   rotate_string_mangle ((u8 *) data, startingsize, next);
522   ((u8 *) data)[startingsize] = 0;
523
524   out_len = startingsize;
525
526   // Copy th result into the output buffer
527   w0[0] = data[0];
528   w0[1] = data[1];
529   w0[2] = data[2];
530   w0[3] = data[3];
531   w1[0] = data[4];
532   w1[1] = data[5];
533   w1[2] = data[6];
534   w1[3] = data[7];
535
536   return (out_len);
537 }