001: package org.python.modules;
002:
003: /* Class for implementing md4 and md5 hash algorithms.
004: * There are constructors for prepping the hash algorithm (doing the
005: * padding, mainly) for a String or a byte[], and an mdcalc() method
006: * for generating the hash. The results can be accessed as an int array
007: * by getregs(), or as a String of hex digits with toString().
008: *
009: * Written for jotp, by Harry Mantakos harry@meretrix.com
010: *
011: * Feel free to do whatever you like with this code.
012: * If you do modify or use this code in another application,
013: * I'd be interested in hearing from you!
014: */
015:
016: class md4 extends md {
017: md4(String s) {
018: super (s);
019: }
020:
021: md4(byte in[]) {
022: super (in);
023: }
024:
025: static int F(int x, int y, int z) {
026: return ((x & y) | (~x & z));
027: }
028:
029: static int G(int x, int y, int z) {
030: return ((x & y) | (x & z) | (y & z));
031: }
032:
033: static int H(int x, int y, int z) {
034: return (x ^ y ^ z);
035: }
036:
037: void round1(int blk) {
038: A = rotintlft((A + F(B, C, D) + d[0 + 16 * blk]), 3);
039: D = rotintlft((D + F(A, B, C) + d[1 + 16 * blk]), 7);
040: C = rotintlft((C + F(D, A, B) + d[2 + 16 * blk]), 11);
041: B = rotintlft((B + F(C, D, A) + d[3 + 16 * blk]), 19);
042:
043: A = rotintlft((A + F(B, C, D) + d[4 + 16 * blk]), 3);
044: D = rotintlft((D + F(A, B, C) + d[5 + 16 * blk]), 7);
045: C = rotintlft((C + F(D, A, B) + d[6 + 16 * blk]), 11);
046: B = rotintlft((B + F(C, D, A) + d[7 + 16 * blk]), 19);
047:
048: A = rotintlft((A + F(B, C, D) + d[8 + 16 * blk]), 3);
049: D = rotintlft((D + F(A, B, C) + d[9 + 16 * blk]), 7);
050: C = rotintlft((C + F(D, A, B) + d[10 + 16 * blk]), 11);
051: B = rotintlft((B + F(C, D, A) + d[11 + 16 * blk]), 19);
052:
053: A = rotintlft((A + F(B, C, D) + d[12 + 16 * blk]), 3);
054: D = rotintlft((D + F(A, B, C) + d[13 + 16 * blk]), 7);
055: C = rotintlft((C + F(D, A, B) + d[14 + 16 * blk]), 11);
056: B = rotintlft((B + F(C, D, A) + d[15 + 16 * blk]), 19);
057: }
058:
059: void round2(int blk) {
060: A = rotintlft((A + G(B, C, D) + d[0 + 16 * blk] + 0x5a827999),
061: 3);
062: D = rotintlft((D + G(A, B, C) + d[4 + 16 * blk] + 0x5a827999),
063: 5);
064: C = rotintlft((C + G(D, A, B) + d[8 + 16 * blk] + 0x5a827999),
065: 9);
066: B = rotintlft((B + G(C, D, A) + d[12 + 16 * blk] + 0x5a827999),
067: 13);
068:
069: A = rotintlft((A + G(B, C, D) + d[1 + 16 * blk] + 0x5a827999),
070: 3);
071: D = rotintlft((D + G(A, B, C) + d[5 + 16 * blk] + 0x5a827999),
072: 5);
073: C = rotintlft((C + G(D, A, B) + d[9 + 16 * blk] + 0x5a827999),
074: 9);
075: B = rotintlft((B + G(C, D, A) + d[13 + 16 * blk] + 0x5a827999),
076: 13);
077:
078: A = rotintlft((A + G(B, C, D) + d[2 + 16 * blk] + 0x5a827999),
079: 3);
080: D = rotintlft((D + G(A, B, C) + d[6 + 16 * blk] + 0x5a827999),
081: 5);
082: C = rotintlft((C + G(D, A, B) + d[10 + 16 * blk] + 0x5a827999),
083: 9);
084: B = rotintlft((B + G(C, D, A) + d[14 + 16 * blk] + 0x5a827999),
085: 13);
086:
087: A = rotintlft((A + G(B, C, D) + d[3 + 16 * blk] + 0x5a827999),
088: 3);
089: D = rotintlft((D + G(A, B, C) + d[7 + 16 * blk] + 0x5a827999),
090: 5);
091: C = rotintlft((C + G(D, A, B) + d[11 + 16 * blk] + 0x5a827999),
092: 9);
093: B = rotintlft((B + G(C, D, A) + d[15 + 16 * blk] + 0x5a827999),
094: 13);
095:
096: }
097:
098: void round3(int blk) {
099: A = rotintlft((A + H(B, C, D) + d[0 + 16 * blk] + 0x6ed9eba1),
100: 3);
101: D = rotintlft((D + H(A, B, C) + d[8 + 16 * blk] + 0x6ed9eba1),
102: 9);
103: C = rotintlft((C + H(D, A, B) + d[4 + 16 * blk] + 0x6ed9eba1),
104: 11);
105: B = rotintlft((B + H(C, D, A) + d[12 + 16 * blk] + 0x6ed9eba1),
106: 15);
107:
108: A = rotintlft((A + H(B, C, D) + d[2 + 16 * blk] + 0x6ed9eba1),
109: 3);
110: D = rotintlft((D + H(A, B, C) + d[10 + 16 * blk] + 0x6ed9eba1),
111: 9);
112: C = rotintlft((C + H(D, A, B) + d[6 + 16 * blk] + 0x6ed9eba1),
113: 11);
114: B = rotintlft((B + H(C, D, A) + d[14 + 16 * blk] + 0x6ed9eba1),
115: 15);
116:
117: A = rotintlft((A + H(B, C, D) + d[1 + 16 * blk] + 0x6ed9eba1),
118: 3);
119: D = rotintlft((D + H(A, B, C) + d[9 + 16 * blk] + 0x6ed9eba1),
120: 9);
121: C = rotintlft((C + H(D, A, B) + d[5 + 16 * blk] + 0x6ed9eba1),
122: 11);
123: B = rotintlft((B + H(C, D, A) + d[13 + 16 * blk] + 0x6ed9eba1),
124: 15);
125:
126: A = rotintlft((A + H(B, C, D) + d[3 + 16 * blk] + 0x6ed9eba1),
127: 3);
128: D = rotintlft((D + H(A, B, C) + d[11 + 16 * blk] + 0x6ed9eba1),
129: 9);
130: C = rotintlft((C + H(D, A, B) + d[7 + 16 * blk] + 0x6ed9eba1),
131: 11);
132: B = rotintlft((B + H(C, D, A) + d[15 + 16 * blk] + 0x6ed9eba1),
133: 15);
134:
135: }
136:
137: void round4(int blk) {
138: System.out.println(" must be md5, in round4!");
139: }
140: }
141:
142: class md5 extends md {
143: md5(String s) {
144: super (s);
145: }
146:
147: md5(byte in[]) {
148: super (in);
149: }
150:
151: static int F(int x, int y, int z) {
152: return ((x & y) | (~x & z));
153: }
154:
155: static int G(int x, int y, int z) {
156: return ((x & z) | (y & ~z));
157: }
158:
159: static int H(int x, int y, int z) {
160: return (x ^ y ^ z);
161: }
162:
163: static int I(int x, int y, int z) {
164: return (y ^ (x | ~z));
165: }
166:
167: void round1(int blk) {
168: A = rotintlft(A + F(B, C, D) + d[0 + 16 * blk] + 0xd76aa478, 7)
169: + B;
170: D = rotintlft(D + F(A, B, C) + d[1 + 16 * blk] + 0xe8c7b756, 12)
171: + A;
172: C = rotintlft(C + F(D, A, B) + d[2 + 16 * blk] + 0x242070db, 17)
173: + D;
174: B = rotintlft(B + F(C, D, A) + d[3 + 16 * blk] + 0xc1bdceee, 22)
175: + C;
176:
177: A = rotintlft(A + F(B, C, D) + d[4 + 16 * blk] + 0xf57c0faf, 7)
178: + B;
179: D = rotintlft(D + F(A, B, C) + d[5 + 16 * blk] + 0x4787c62a, 12)
180: + A;
181: C = rotintlft(C + F(D, A, B) + d[6 + 16 * blk] + 0xa8304613, 17)
182: + D;
183: B = rotintlft(B + F(C, D, A) + d[7 + 16 * blk] + 0xfd469501, 22)
184: + C;
185: A = rotintlft(A + F(B, C, D) + d[8 + 16 * blk] + 0x698098d8, 7)
186: + B;
187: D = rotintlft(D + F(A, B, C) + d[9 + 16 * blk] + 0x8b44f7af, 12)
188: + A;
189: C = rotintlft(C + F(D, A, B) + d[10 + 16 * blk] + 0xffff5bb1,
190: 17)
191: + D;
192: B = rotintlft(B + F(C, D, A) + d[11 + 16 * blk] + 0x895cd7be,
193: 22)
194: + C;
195: A = rotintlft(A + F(B, C, D) + d[12 + 16 * blk] + 0x6b901122, 7)
196: + B;
197: D = rotintlft(D + F(A, B, C) + d[13 + 16 * blk] + 0xfd987193,
198: 12)
199: + A;
200: C = rotintlft(C + F(D, A, B) + d[14 + 16 * blk] + 0xa679438e,
201: 17)
202: + D;
203: B = rotintlft(B + F(C, D, A) + d[15 + 16 * blk] + 0x49b40821,
204: 22)
205: + C;
206: }
207:
208: void round2(int blk) {
209: A = rotintlft(A + G(B, C, D) + d[1 + 16 * blk] + 0xf61e2562, 5)
210: + B;
211: D = rotintlft(D + G(A, B, C) + d[6 + 16 * blk] + 0xc040b340, 9)
212: + A;
213: C = rotintlft(C + G(D, A, B) + d[11 + 16 * blk] + 0x265e5a51,
214: 14)
215: + D;
216: B = rotintlft(B + G(C, D, A) + d[0 + 16 * blk] + 0xe9b6c7aa, 20)
217: + C;
218: A = rotintlft(A + G(B, C, D) + d[5 + 16 * blk] + 0xd62f105d, 5)
219: + B;
220: D = rotintlft(D + G(A, B, C) + d[10 + 16 * blk] + 0x02441453, 9)
221: + A;
222: C = rotintlft(C + G(D, A, B) + d[15 + 16 * blk] + 0xd8a1e681,
223: 14)
224: + D;
225: B = rotintlft(B + G(C, D, A) + d[4 + 16 * blk] + 0xe7d3fbc8, 20)
226: + C;
227: A = rotintlft(A + G(B, C, D) + d[9 + 16 * blk] + 0x21e1cde6, 5)
228: + B;
229: D = rotintlft(D + G(A, B, C) + d[14 + 16 * blk] + 0xc33707d6, 9)
230: + A;
231: C = rotintlft(C + G(D, A, B) + d[3 + 16 * blk] + 0xf4d50d87, 14)
232: + D;
233: B = rotintlft(B + G(C, D, A) + d[8 + 16 * blk] + 0x455a14ed, 20)
234: + C;
235: A = rotintlft(A + G(B, C, D) + d[13 + 16 * blk] + 0xa9e3e905, 5)
236: + B;
237: D = rotintlft(D + G(A, B, C) + d[2 + 16 * blk] + 0xfcefa3f8, 9)
238: + A;
239: C = rotintlft(C + G(D, A, B) + d[7 + 16 * blk] + 0x676f02d9, 14)
240: + D;
241: B = rotintlft(B + G(C, D, A) + d[12 + 16 * blk] + 0x8d2a4c8a,
242: 20)
243: + C;
244: }
245:
246: void round3(int blk) {
247: A = rotintlft(A + H(B, C, D) + d[5 + 16 * blk] + 0xfffa3942, 4)
248: + B;
249: D = rotintlft(D + H(A, B, C) + d[8 + 16 * blk] + 0x8771f681, 11)
250: + A;
251: C = rotintlft(C + H(D, A, B) + d[11 + 16 * blk] + 0x6d9d6122,
252: 16)
253: + D;
254: B = rotintlft(B + H(C, D, A) + d[14 + 16 * blk] + 0xfde5380c,
255: 23)
256: + C;
257: A = rotintlft(A + H(B, C, D) + d[1 + 16 * blk] + 0xa4beea44, 4)
258: + B;
259: D = rotintlft(D + H(A, B, C) + d[4 + 16 * blk] + 0x4bdecfa9, 11)
260: + A;
261: C = rotintlft(C + H(D, A, B) + d[7 + 16 * blk] + 0xf6bb4b60, 16)
262: + D;
263: B = rotintlft(B + H(C, D, A) + d[10 + 16 * blk] + 0xbebfbc70,
264: 23)
265: + C;
266: A = rotintlft(A + H(B, C, D) + d[13 + 16 * blk] + 0x289b7ec6, 4)
267: + B;
268: D = rotintlft(D + H(A, B, C) + d[0 + 16 * blk] + 0xeaa127fa, 11)
269: + A;
270: C = rotintlft(C + H(D, A, B) + d[3 + 16 * blk] + 0xd4ef3085, 16)
271: + D;
272: B = rotintlft(B + H(C, D, A) + d[6 + 16 * blk] + 0x04881d05, 23)
273: + C;
274: A = rotintlft(A + H(B, C, D) + d[9 + 16 * blk] + 0xd9d4d039, 4)
275: + B;
276: D = rotintlft(D + H(A, B, C) + d[12 + 16 * blk] + 0xe6db99e5,
277: 11)
278: + A;
279: C = rotintlft(C + H(D, A, B) + d[15 + 16 * blk] + 0x1fa27cf8,
280: 16)
281: + D;
282: B = rotintlft(B + H(C, D, A) + d[2 + 16 * blk] + 0xc4ac5665, 23)
283: + C;
284: }
285:
286: void round4(int blk) {
287: A = rotintlft(A + I(B, C, D) + d[0 + 16 * blk] + 0xf4292244, 6)
288: + B;
289: D = rotintlft(D + I(A, B, C) + d[7 + 16 * blk] + 0x432aff97, 10)
290: + A;
291: C = rotintlft(C + I(D, A, B) + d[14 + 16 * blk] + 0xab9423a7,
292: 15)
293: + D;
294: B = rotintlft(B + I(C, D, A) + d[5 + 16 * blk] + 0xfc93a039, 21)
295: + C;
296: A = rotintlft(A + I(B, C, D) + d[12 + 16 * blk] + 0x655b59c3, 6)
297: + B;
298: D = rotintlft(D + I(A, B, C) + d[3 + 16 * blk] + 0x8f0ccc92, 10)
299: + A;
300: C = rotintlft(C + I(D, A, B) + d[10 + 16 * blk] + 0xffeff47d,
301: 15)
302: + D;
303: B = rotintlft(B + I(C, D, A) + d[1 + 16 * blk] + 0x85845dd1, 21)
304: + C;
305: A = rotintlft(A + I(B, C, D) + d[8 + 16 * blk] + 0x6fa87e4f, 6)
306: + B;
307: D = rotintlft(D + I(A, B, C) + d[15 + 16 * blk] + 0xfe2ce6e0,
308: 10)
309: + A;
310: C = rotintlft(C + I(D, A, B) + d[6 + 16 * blk] + 0xa3014314, 15)
311: + D;
312: B = rotintlft(B + I(C, D, A) + d[13 + 16 * blk] + 0x4e0811a1,
313: 21)
314: + C;
315: A = rotintlft(A + I(B, C, D) + d[4 + 16 * blk] + 0xf7537e82, 6)
316: + B;
317: D = rotintlft(D + I(A, B, C) + d[11 + 16 * blk] + 0xbd3af235,
318: 10)
319: + A;
320: C = rotintlft(C + I(D, A, B) + d[2 + 16 * blk] + 0x2ad7d2bb, 15)
321: + D;
322: B = rotintlft(B + I(C, D, A) + d[9 + 16 * blk] + 0xeb86d391, 21)
323: + C;
324: }
325: }
326:
327: class md {
328: int A, B, C, D;
329: int d[];
330: int numwords;
331:
332: /* For verification of a modicum of sanity, run a few
333: * test strings through
334: */
335: public static void main(String argv[]) {
336: boolean doinmd4;
337: String mdtype;
338: /* Test cases, mostly taken from rfc 1320 */
339: String str[] = {
340: "",
341: "a",
342: "abc",
343: "message digest",
344: "abcdefghijklmnopqrstuvwxyz",
345: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
346: "12345678901234567890123456789012345678901234567890123456789012"
347: + "345678901234567890",
348: "01234567890123456789012345678901234567890123456789012345" };
349:
350: if (argv.length == 0) {
351: mdtype = "md4";
352: doinmd4 = true;
353: } else if (argv.length > 1) {
354: System.err.println("Usage: md [4|5|md4|md5]");
355: return;
356: } else if ((argv[0].equals("4")) || (argv[0].equals("md4"))) {
357: mdtype = "md4";
358: doinmd4 = true;
359: } else if ((argv[0].equals("5")) || (argv[0].equals("md5"))) {
360: mdtype = "md5";
361: doinmd4 = false;
362: } else {
363: System.err.println("Usage: md [4|5|md4|md5]");
364: return;
365: }
366: for (int i = 0; i < str.length; i++) {
367: if (doinmd4) {
368: md4 mdc = new md4(str[i]);
369: mdc.calc();
370: System.out.println(mdtype + "(\"" + str[i] + "\") = "
371: + mdc);
372: } else {
373: md5 mdc = new md5(str[i]);
374: mdc.calc();
375: System.out.println(mdtype + "(\"" + str[i] + "\") = "
376: + mdc);
377: }
378: }
379: }
380:
381: md(String s) {
382: byte in[] = new byte[s.length()];
383: int i;
384:
385: for (i = 0; i < s.length(); i++) {
386: in[i] = (byte) (s.charAt(i) & 0xff);
387: }
388: mdinit(in);
389: }
390:
391: md(byte in[]) {
392: mdinit(in);
393: }
394:
395: void mdinit(byte in[]) {
396: int newlen, endblklen, pad, i;
397: long datalenbits;
398:
399: datalenbits = in.length * 8;
400: endblklen = in.length % 64;
401: if (endblklen < 56) {
402: pad = 64 - endblklen;
403: } else {
404: pad = (64 - endblklen) + 64;
405: }
406: newlen = in.length + pad;
407: byte b[] = new byte[newlen];
408: for (i = 0; i < in.length; i++) {
409: b[i] = in[i];
410: }
411: b[in.length] = (byte) 0x80;
412: for (i = b.length + 1; i < (newlen - 8); i++) {
413: b[i] = 0;
414: }
415: for (i = 0; i < 8; i++) {
416: b[newlen - 8 + i] = (byte) (datalenbits & 0xff);
417: datalenbits >>= 8;
418: }
419: /* init registers */
420: A = 0x67452301;
421: B = 0xefcdab89;
422: C = 0x98badcfe;
423: D = 0x10325476;
424: this .numwords = newlen / 4;
425: this .d = new int[this .numwords];
426: for (i = 0; i < newlen; i += 4) {
427: this .d[i / 4] = (b[i] & 0xff) + ((b[i + 1] & 0xff) << 8)
428: + ((b[i + 2] & 0xff) << 16)
429: + ((b[i + 3] & 0xff) << 24);
430: }
431: }
432:
433: public String toString() {
434: String s;
435:
436: return (tohex(A) + tohex(B) + tohex(C) + tohex(D));
437: }
438:
439: int[] getregs() {
440: int regs[] = { this .A, this .B, this .C, this .D };
441:
442: return regs;
443: }
444:
445: void calc() {
446: int AA, BB, CC, DD, i;
447:
448: for (i = 0; i < numwords / 16; i++) {
449: AA = A;
450: BB = B;
451: CC = C;
452: DD = D;
453: round1(i);
454: round2(i);
455: round3(i);
456: if (this instanceof md5) {
457: round4(i);
458: }
459: A += AA;
460: B += BB;
461: C += CC;
462: D += DD;
463: }
464: }
465:
466: /* Dummy round*() methods. these are overriden in the md4 and md5
467: * subclasses
468: */
469: void round1(int blk) {
470: System.err
471: .println("Danger! Danger! Someone called md.round1()!");
472: }
473:
474: void round2(int blk) {
475: System.err
476: .println("Danger! Danger! Someone called md.round2()!");
477: }
478:
479: void round3(int blk) {
480: System.err
481: .println("Danger! Danger! Someone called md.round3()!");
482: }
483:
484: void round4(int blk) {
485: System.err
486: .println("Danger! Danger! Someone called md.round4()!");
487: }
488:
489: static int rotintlft(int val, int numbits) {
490: return ((val << numbits) | (val >>> (32 - numbits)));
491: }
492:
493: static String tohex(int i) {
494: int b;
495: String tmpstr;
496:
497: tmpstr = "";
498: for (b = 0; b < 4; b++) {
499: tmpstr += Integer.toString((i >> 4) & 0xf, 16)
500: + Integer.toString(i & 0xf, 16);
501: i >>= 8;
502: }
503: return tmpstr;
504: }
505:
506: static md new_md5(String data) {
507: return new md5(data);
508: }
509:
510: }
|