001: // This file is currently unlocked (change this line if you lock the file)
002: //
003: // $Log: MD4.java,v $
004: // Revision 1.2 1998/01/05 03:41:19 iang
005: // Added references only.
006: //
007: // Revision 1.1.1.1 1997/11/03 22:36:56 hopwood
008: // + Imported to CVS (tagged as 'start').
009: //
010: // Revision 0.1.0.0 1997/07/14 R. Naffah
011: // + original version
012: //
013: // $Endlog$
014: /*
015: * Copyright (c) 1997 Systemics Ltd
016: * on behalf of the Cryptix Development Team. All rights reserved.
017: */
018:
019: package jcifs.util;
020:
021: import java.security.MessageDigest;
022:
023: /**
024: * Implements the MD4 message digest algorithm in Java.
025: * <p>
026: * <b>References:</b>
027: * <ol>
028: * <li> Ronald L. Rivest,
029: * "<a href="http://www.roxen.com/rfc/rfc1320.html">
030: * The MD4 Message-Digest Algorithm</a>",
031: * IETF RFC-1320 (informational).
032: * </ol>
033: *
034: * <p><b>$Revision: 1.2 $</b>
035: * @author Raif S. Naffah
036: */
037: public class MD4 extends MessageDigest implements Cloneable {
038: // MD4 specific object variables
039: //...........................................................................
040:
041: /**
042: * The size in bytes of the input block to the tranformation algorithm.
043: */
044: private static final int BLOCK_LENGTH = 64; // = 512 / 8;
045:
046: /**
047: * 4 32-bit words (interim result)
048: */
049: private int[] context = new int[4];
050:
051: /**
052: * Number of bytes processed so far mod. 2 power of 64.
053: */
054: private long count;
055:
056: /**
057: * 512 bits input buffer = 16 x 32-bit words holds until reaches 512 bits.
058: */
059: private byte[] buffer = new byte[BLOCK_LENGTH];
060:
061: /**
062: * 512 bits work buffer = 16 x 32-bit words
063: */
064: private int[] X = new int[16];
065:
066: // Constructors
067: //...........................................................................
068:
069: public MD4() {
070: super ("MD4");
071: engineReset();
072: }
073:
074: /**
075: * This constructor is here to implement cloneability of this class.
076: */
077: private MD4(MD4 md) {
078: this ();
079: context = (int[]) md.context.clone();
080: buffer = (byte[]) md.buffer.clone();
081: count = md.count;
082: }
083:
084: // Cloneable method implementation
085: //...........................................................................
086:
087: /**
088: * Returns a copy of this MD object.
089: */
090: public Object clone() {
091: return new MD4(this );
092: }
093:
094: // JCE methods
095: //...........................................................................
096:
097: /**
098: * Resets this object disregarding any temporary data present at the
099: * time of the invocation of this call.
100: */
101: public void engineReset() {
102: // initial values of MD4 i.e. A, B, C, D
103: // as per rfc-1320; they are low-order byte first
104: context[0] = 0x67452301;
105: context[1] = 0xEFCDAB89;
106: context[2] = 0x98BADCFE;
107: context[3] = 0x10325476;
108: count = 0L;
109: for (int i = 0; i < BLOCK_LENGTH; i++)
110: buffer[i] = 0;
111: }
112:
113: /**
114: * Continues an MD4 message digest using the input byte.
115: */
116: public void engineUpdate(byte b) {
117: // compute number of bytes still unhashed; ie. present in buffer
118: int i = (int) (count % BLOCK_LENGTH);
119: count++; // update number of bytes
120: buffer[i] = b;
121: if (i == BLOCK_LENGTH - 1)
122: transform(buffer, 0);
123: }
124:
125: /**
126: * MD4 block update operation.
127: * <p>
128: * Continues an MD4 message digest operation, by filling the buffer,
129: * transform(ing) data in 512-bit message block(s), updating the variables
130: * context and count, and leaving (buffering) the remaining bytes in buffer
131: * for the next update or finish.
132: *
133: * @param input input block
134: * @param offset start of meaningful bytes in input
135: * @param len count of bytes in input block to consider
136: */
137: public void engineUpdate(byte[] input, int offset, int len) {
138: // make sure we don't exceed input's allocated size/length
139: if (offset < 0 || len < 0 || (long) offset + len > input.length)
140: throw new ArrayIndexOutOfBoundsException();
141:
142: // compute number of bytes still unhashed; ie. present in buffer
143: int bufferNdx = (int) (count % BLOCK_LENGTH);
144: count += len; // update number of bytes
145: int partLen = BLOCK_LENGTH - bufferNdx;
146: int i = 0;
147: if (len >= partLen) {
148: System.arraycopy(input, offset, buffer, bufferNdx, partLen);
149:
150: transform(buffer, 0);
151:
152: for (i = partLen; i + BLOCK_LENGTH - 1 < len; i += BLOCK_LENGTH)
153: transform(input, offset + i);
154: bufferNdx = 0;
155: }
156: // buffer remaining input
157: if (i < len)
158: System.arraycopy(input, offset + i, buffer, bufferNdx, len
159: - i);
160: }
161:
162: /**
163: * Completes the hash computation by performing final operations such
164: * as padding. At the return of this engineDigest, the MD engine is
165: * reset.
166: *
167: * @return the array of bytes for the resulting hash value.
168: */
169: public byte[] engineDigest() {
170: // pad output to 56 mod 64; as RFC1320 puts it: congruent to 448 mod 512
171: int bufferNdx = (int) (count % BLOCK_LENGTH);
172: int padLen = (bufferNdx < 56) ? (56 - bufferNdx)
173: : (120 - bufferNdx);
174:
175: // padding is alwas binary 1 followed by binary 0s
176: byte[] tail = new byte[padLen + 8];
177: tail[0] = (byte) 0x80;
178:
179: // append length before final transform:
180: // save number of bits, casting the long to an array of 8 bytes
181: // save low-order byte first.
182: for (int i = 0; i < 8; i++)
183: tail[padLen + i] = (byte) ((count * 8) >>> (8 * i));
184:
185: engineUpdate(tail, 0, tail.length);
186:
187: byte[] result = new byte[16];
188: // cast this MD4's context (array of 4 ints) into an array of 16 bytes.
189: for (int i = 0; i < 4; i++)
190: for (int j = 0; j < 4; j++)
191: result[i * 4 + j] = (byte) (context[i] >>> (8 * j));
192:
193: // reset the engine
194: engineReset();
195: return result;
196: }
197:
198: // own methods
199: //...........................................................................
200:
201: /**
202: * MD4 basic transformation.
203: * <p>
204: * Transforms context based on 512 bits from input block starting
205: * from the offset'th byte.
206: *
207: * @param block input sub-array.
208: * @param offset starting position of sub-array.
209: */
210: private void transform(byte[] block, int offset) {
211:
212: // encodes 64 bytes from input block into an array of 16 32-bit
213: // entities. Use A as a temp var.
214: for (int i = 0; i < 16; i++)
215: X[i] = (block[offset++] & 0xFF)
216: | (block[offset++] & 0xFF) << 8
217: | (block[offset++] & 0xFF) << 16
218: | (block[offset++] & 0xFF) << 24;
219:
220: int A = context[0];
221: int B = context[1];
222: int C = context[2];
223: int D = context[3];
224:
225: A = FF(A, B, C, D, X[0], 3);
226: D = FF(D, A, B, C, X[1], 7);
227: C = FF(C, D, A, B, X[2], 11);
228: B = FF(B, C, D, A, X[3], 19);
229: A = FF(A, B, C, D, X[4], 3);
230: D = FF(D, A, B, C, X[5], 7);
231: C = FF(C, D, A, B, X[6], 11);
232: B = FF(B, C, D, A, X[7], 19);
233: A = FF(A, B, C, D, X[8], 3);
234: D = FF(D, A, B, C, X[9], 7);
235: C = FF(C, D, A, B, X[10], 11);
236: B = FF(B, C, D, A, X[11], 19);
237: A = FF(A, B, C, D, X[12], 3);
238: D = FF(D, A, B, C, X[13], 7);
239: C = FF(C, D, A, B, X[14], 11);
240: B = FF(B, C, D, A, X[15], 19);
241:
242: A = GG(A, B, C, D, X[0], 3);
243: D = GG(D, A, B, C, X[4], 5);
244: C = GG(C, D, A, B, X[8], 9);
245: B = GG(B, C, D, A, X[12], 13);
246: A = GG(A, B, C, D, X[1], 3);
247: D = GG(D, A, B, C, X[5], 5);
248: C = GG(C, D, A, B, X[9], 9);
249: B = GG(B, C, D, A, X[13], 13);
250: A = GG(A, B, C, D, X[2], 3);
251: D = GG(D, A, B, C, X[6], 5);
252: C = GG(C, D, A, B, X[10], 9);
253: B = GG(B, C, D, A, X[14], 13);
254: A = GG(A, B, C, D, X[3], 3);
255: D = GG(D, A, B, C, X[7], 5);
256: C = GG(C, D, A, B, X[11], 9);
257: B = GG(B, C, D, A, X[15], 13);
258:
259: A = HH(A, B, C, D, X[0], 3);
260: D = HH(D, A, B, C, X[8], 9);
261: C = HH(C, D, A, B, X[4], 11);
262: B = HH(B, C, D, A, X[12], 15);
263: A = HH(A, B, C, D, X[2], 3);
264: D = HH(D, A, B, C, X[10], 9);
265: C = HH(C, D, A, B, X[6], 11);
266: B = HH(B, C, D, A, X[14], 15);
267: A = HH(A, B, C, D, X[1], 3);
268: D = HH(D, A, B, C, X[9], 9);
269: C = HH(C, D, A, B, X[5], 11);
270: B = HH(B, C, D, A, X[13], 15);
271: A = HH(A, B, C, D, X[3], 3);
272: D = HH(D, A, B, C, X[11], 9);
273: C = HH(C, D, A, B, X[7], 11);
274: B = HH(B, C, D, A, X[15], 15);
275:
276: context[0] += A;
277: context[1] += B;
278: context[2] += C;
279: context[3] += D;
280: }
281:
282: // The basic MD4 atomic functions.
283:
284: private int FF(int a, int b, int c, int d, int x, int s) {
285: int t = a + ((b & c) | (~b & d)) + x;
286: return t << s | t >>> (32 - s);
287: }
288:
289: private int GG(int a, int b, int c, int d, int x, int s) {
290: int t = a + ((b & (c | d)) | (c & d)) + x + 0x5A827999;
291: return t << s | t >>> (32 - s);
292: }
293:
294: private int HH(int a, int b, int c, int d, int x, int s) {
295: int t = a + (b ^ c ^ d) + x + 0x6ED9EBA1;
296: return t << s | t >>> (32 - s);
297: }
298: }
|