001: /*
002:
003: This software is OSI Certified Open Source Software.
004: OSI Certified is a certification mark of the Open Source Initiative.
005:
006: The license (Mozilla version 1.0) can be read at the MMBase site.
007: See http://www.MMBase.org/license
008:
009: */
010: package org.mmbase.util.transformers;
011:
012: /**
013: * Do MD5 encoding. Decoding is of course not possible. MD5 encoding
014: * can not be efficiently 'piped', because the complete String is
015: * needed. So, be careful 'chaining' it.
016: *
017: * @author Michiel Meeuwissen
018: * @version $Id: MD5.java,v 1.7 2003/05/12 14:33:00 kees Exp $
019: */
020:
021: public class MD5 extends StringTransformer implements CharTransformer {
022: private final static String ENCODING = "MD5";
023: private MD5Implementation transformer = new MD5Implementation();
024:
025: public String toString() {
026: return ENCODING;
027: }
028:
029: public String transform(String r) {
030: return transformer.calcMD5(r);
031: }
032:
033: public String transformBack(String w) {
034: throw new UnsupportedOperationException(
035: "transformBack(String) can never be done for MD5(i hope so :p)");
036: }
037:
038: // from http://pajhome.org.uk/crypt/md5/md5.java.txt
039: // With permission of Thomas Weber (tw@orange-interactive.de)
040: class MD5Implementation {
041: /*
042: * A Java implementation of the RSA Data Security, Inc. MD5 Message
043: * Digest Algorithm, as defined in RFC 1321.
044: * Based on the JavaScript implementation of Paul Johnston
045: * Copyright (C) Paul Johnston 1999 - 2000.
046: * See http://pajhome.org.uk/site/legal.html for details.
047: * Java Version by Thomas Weber (Orange Interactive GmbH)
048: */
049:
050: /*
051: * Convert a 32-bit number to a hex string with ls-byte first
052: */
053: String hex_chr = "0123456789abcdef";
054:
055: private String rhex(int num) {
056: String str = "";
057: for (int j = 0; j <= 3; j++)
058: str = str + hex_chr.charAt((num >> (j * 8 + 4)) & 0x0F)
059: + hex_chr.charAt((num >> (j * 8)) & 0x0F);
060: return str;
061: }
062:
063: /*
064: * Convert a string to a sequence of 16-word blocks, stored as an array.
065: * Append padding bits and the length, as described in the MD5 standard.
066: */
067: private int[] str2blks_MD5(String str) {
068: int nblk = ((str.length() + 8) >> 6) + 1;
069: int[] blks = new int[nblk * 16];
070: int i = 0;
071: for (i = 0; i < nblk * 16; i++) {
072: blks[i] = 0;
073: }
074: for (i = 0; i < str.length(); i++) {
075: blks[i >> 2] |= str.charAt(i) << ((i % 4) * 8);
076: }
077: blks[i >> 2] |= 0x80 << ((i % 4) * 8);
078: blks[nblk * 16 - 2] = str.length() * 8;
079:
080: return blks;
081: }
082:
083: /*
084: * Add integers, wrapping at 2^32
085: */
086: private int add(int x, int y) {
087: return ((x & 0x7FFFFFFF) + (y & 0x7FFFFFFF))
088: ^ (x & 0x80000000) ^ (y & 0x80000000);
089: }
090:
091: /*
092: * Bitwise rotate a 32-bit number to the left
093: */
094: private int rol(int num, int cnt) {
095: return (num << cnt) | (num >>> (32 - cnt));
096: }
097:
098: /*
099: * These functions implement the basic operation for each round of the
100: * algorithm.
101: */
102: private int cmn(int q, int a, int b, int x, int s, int t) {
103: return add(rol(add(add(a, q), add(x, t)), s), b);
104: }
105:
106: private int ff(int a, int b, int c, int d, int x, int s, int t) {
107: return cmn((b & c) | ((~b) & d), a, b, x, s, t);
108: }
109:
110: private int gg(int a, int b, int c, int d, int x, int s, int t) {
111: return cmn((b & d) | (c & (~d)), a, b, x, s, t);
112: }
113:
114: private int hh(int a, int b, int c, int d, int x, int s, int t) {
115: return cmn(b ^ c ^ d, a, b, x, s, t);
116: }
117:
118: private int ii(int a, int b, int c, int d, int x, int s, int t) {
119: return cmn(c ^ (b | (~d)), a, b, x, s, t);
120: }
121:
122: /*
123: * Take a string and return the hex representation of its MD5.
124: */
125: public String calcMD5(String str) {
126: int[] x = str2blks_MD5(str);
127: int a = 0x67452301;
128: int b = 0xEFCDAB89;
129: int c = 0x98BADCFE;
130: int d = 0x10325476;
131:
132: for (int i = 0; i < x.length; i += 16) {
133: int olda = a;
134: int oldb = b;
135: int oldc = c;
136: int oldd = d;
137:
138: a = ff(a, b, c, d, x[i + 0], 7, 0xD76AA478);
139: d = ff(d, a, b, c, x[i + 1], 12, 0xE8C7B756);
140: c = ff(c, d, a, b, x[i + 2], 17, 0x242070DB);
141: b = ff(b, c, d, a, x[i + 3], 22, 0xC1BDCEEE);
142: a = ff(a, b, c, d, x[i + 4], 7, 0xF57C0FAF);
143: d = ff(d, a, b, c, x[i + 5], 12, 0x4787C62A);
144: c = ff(c, d, a, b, x[i + 6], 17, 0xA8304613);
145: b = ff(b, c, d, a, x[i + 7], 22, 0xFD469501);
146: a = ff(a, b, c, d, x[i + 8], 7, 0x698098D8);
147: d = ff(d, a, b, c, x[i + 9], 12, 0x8B44F7AF);
148: c = ff(c, d, a, b, x[i + 10], 17, 0xFFFF5BB1);
149: b = ff(b, c, d, a, x[i + 11], 22, 0x895CD7BE);
150: a = ff(a, b, c, d, x[i + 12], 7, 0x6B901122);
151: d = ff(d, a, b, c, x[i + 13], 12, 0xFD987193);
152: c = ff(c, d, a, b, x[i + 14], 17, 0xA679438E);
153: b = ff(b, c, d, a, x[i + 15], 22, 0x49B40821);
154:
155: a = gg(a, b, c, d, x[i + 1], 5, 0xF61E2562);
156: d = gg(d, a, b, c, x[i + 6], 9, 0xC040B340);
157: c = gg(c, d, a, b, x[i + 11], 14, 0x265E5A51);
158: b = gg(b, c, d, a, x[i + 0], 20, 0xE9B6C7AA);
159: a = gg(a, b, c, d, x[i + 5], 5, 0xD62F105D);
160: d = gg(d, a, b, c, x[i + 10], 9, 0x02441453);
161: c = gg(c, d, a, b, x[i + 15], 14, 0xD8A1E681);
162: b = gg(b, c, d, a, x[i + 4], 20, 0xE7D3FBC8);
163: a = gg(a, b, c, d, x[i + 9], 5, 0x21E1CDE6);
164: d = gg(d, a, b, c, x[i + 14], 9, 0xC33707D6);
165: c = gg(c, d, a, b, x[i + 3], 14, 0xF4D50D87);
166: b = gg(b, c, d, a, x[i + 8], 20, 0x455A14ED);
167: a = gg(a, b, c, d, x[i + 13], 5, 0xA9E3E905);
168: d = gg(d, a, b, c, x[i + 2], 9, 0xFCEFA3F8);
169: c = gg(c, d, a, b, x[i + 7], 14, 0x676F02D9);
170: b = gg(b, c, d, a, x[i + 12], 20, 0x8D2A4C8A);
171:
172: a = hh(a, b, c, d, x[i + 5], 4, 0xFFFA3942);
173: d = hh(d, a, b, c, x[i + 8], 11, 0x8771F681);
174: c = hh(c, d, a, b, x[i + 11], 16, 0x6D9D6122);
175: b = hh(b, c, d, a, x[i + 14], 23, 0xFDE5380C);
176: a = hh(a, b, c, d, x[i + 1], 4, 0xA4BEEA44);
177: d = hh(d, a, b, c, x[i + 4], 11, 0x4BDECFA9);
178: c = hh(c, d, a, b, x[i + 7], 16, 0xF6BB4B60);
179: b = hh(b, c, d, a, x[i + 10], 23, 0xBEBFBC70);
180: a = hh(a, b, c, d, x[i + 13], 4, 0x289B7EC6);
181: d = hh(d, a, b, c, x[i + 0], 11, 0xEAA127FA);
182: c = hh(c, d, a, b, x[i + 3], 16, 0xD4EF3085);
183: b = hh(b, c, d, a, x[i + 6], 23, 0x04881D05);
184: a = hh(a, b, c, d, x[i + 9], 4, 0xD9D4D039);
185: d = hh(d, a, b, c, x[i + 12], 11, 0xE6DB99E5);
186: c = hh(c, d, a, b, x[i + 15], 16, 0x1FA27CF8);
187: b = hh(b, c, d, a, x[i + 2], 23, 0xC4AC5665);
188:
189: a = ii(a, b, c, d, x[i + 0], 6, 0xF4292244);
190: d = ii(d, a, b, c, x[i + 7], 10, 0x432AFF97);
191: c = ii(c, d, a, b, x[i + 14], 15, 0xAB9423A7);
192: b = ii(b, c, d, a, x[i + 5], 21, 0xFC93A039);
193: a = ii(a, b, c, d, x[i + 12], 6, 0x655B59C3);
194: d = ii(d, a, b, c, x[i + 3], 10, 0x8F0CCC92);
195: c = ii(c, d, a, b, x[i + 10], 15, 0xFFEFF47D);
196: b = ii(b, c, d, a, x[i + 1], 21, 0x85845DD1);
197: a = ii(a, b, c, d, x[i + 8], 6, 0x6FA87E4F);
198: d = ii(d, a, b, c, x[i + 15], 10, 0xFE2CE6E0);
199: c = ii(c, d, a, b, x[i + 6], 15, 0xA3014314);
200: b = ii(b, c, d, a, x[i + 13], 21, 0x4E0811A1);
201: a = ii(a, b, c, d, x[i + 4], 6, 0xF7537E82);
202: d = ii(d, a, b, c, x[i + 11], 10, 0xBD3AF235);
203: c = ii(c, d, a, b, x[i + 2], 15, 0x2AD7D2BB);
204: b = ii(b, c, d, a, x[i + 9], 21, 0xEB86D391);
205:
206: a = add(a, olda);
207: b = add(b, oldb);
208: c = add(c, oldc);
209: d = add(d, oldd);
210: }
211: return rhex(a) + rhex(b) + rhex(c) + rhex(d);
212: }
213: }
214: }
|