KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jcifs > util > MD4


1 // This file is currently unlocked (change this line if you lock the file)
2
//
3
// $Log: MD4.java,v $
4
// Revision 1.2 1998/01/05 03:41:19 iang
5
// Added references only.
6
//
7
// Revision 1.1.1.1 1997/11/03 22:36:56 hopwood
8
// + Imported to CVS (tagged as 'start').
9
//
10
// Revision 0.1.0.0 1997/07/14 R. Naffah
11
// + original version
12
//
13
// $Endlog$
14
/*
15  * Copyright (c) 1997 Systemics Ltd
16  * on behalf of the Cryptix Development Team. All rights reserved.
17  */

18
19 package jcifs.util;
20
21 import java.security.MessageDigest JavaDoc;
22
23 /**
24  * Implements the MD4 message digest algorithm in Java.
25  * <p>
26  * <b>References:</b>
27  * <ol>
28  * <li> Ronald L. Rivest,
29  * "<a HREF="http://www.roxen.com/rfc/rfc1320.html">
30  * The MD4 Message-Digest Algorithm</a>",
31  * IETF RFC-1320 (informational).
32  * </ol>
33  *
34  * <p><b>$Revision: 1.2 $</b>
35  * @author Raif S. Naffah
36  */

37 public class MD4 extends MessageDigest JavaDoc implements Cloneable JavaDoc
38 {
39 // MD4 specific object variables
40
//...........................................................................
41

42     /**
43      * The size in bytes of the input block to the tranformation algorithm.
44      */

45     private static final int BLOCK_LENGTH = 64; // = 512 / 8;
46

47     /**
48      * 4 32-bit words (interim result)
49      */

50     private int[] context = new int[4];
51
52     /**
53      * Number of bytes processed so far mod. 2 power of 64.
54      */

55     private long count;
56
57     /**
58      * 512 bits input buffer = 16 x 32-bit words holds until reaches 512 bits.
59      */

60     private byte[] buffer = new byte[BLOCK_LENGTH];
61
62     /**
63      * 512 bits work buffer = 16 x 32-bit words
64      */

65     private int[] X = new int[16];
66
67
68 // Constructors
69
//...........................................................................
70

71     public MD4 () {
72         super("MD4");
73         engineReset();
74     }
75
76     /**
77      * This constructor is here to implement cloneability of this class.
78      */

79     private MD4 (MD4 md) {
80         this();
81         context = (int[])md.context.clone();
82         buffer = (byte[])md.buffer.clone();
83         count = md.count;
84     }
85
86
87 // Cloneable method implementation
88
//...........................................................................
89

90     /**
91      * Returns a copy of this MD object.
92      */

93     public Object JavaDoc clone() { return new MD4(this); }
94
95
96 // JCE methods
97
//...........................................................................
98

99     /**
100      * Resets this object disregarding any temporary data present at the
101      * time of the invocation of this call.
102      */

103     public void engineReset () {
104         // initial values of MD4 i.e. A, B, C, D
105
// as per rfc-1320; they are low-order byte first
106
context[0] = 0x67452301;
107         context[1] = 0xEFCDAB89;
108         context[2] = 0x98BADCFE;
109         context[3] = 0x10325476;
110         count = 0L;
111         for (int i = 0; i < BLOCK_LENGTH; i++)
112             buffer[i] = 0;
113     }
114
115     /**
116      * Continues an MD4 message digest using the input byte.
117      */

118     public void engineUpdate (byte b) {
119         // compute number of bytes still unhashed; ie. present in buffer
120
int i = (int)(count % BLOCK_LENGTH);
121         count++; // update number of bytes
122
buffer[i] = b;
123         if (i == BLOCK_LENGTH - 1)
124             transform(buffer, 0);
125     }
126
127     /**
128      * MD4 block update operation.
129      * <p>
130      * Continues an MD4 message digest operation, by filling the buffer,
131      * transform(ing) data in 512-bit message block(s), updating the variables
132      * context and count, and leaving (buffering) the remaining bytes in buffer
133      * for the next update or finish.
134      *
135      * @param input input block
136      * @param offset start of meaningful bytes in input
137      * @param len count of bytes in input block to consider
138      */

139     public void engineUpdate (byte[] input, int offset, int len) {
140         // make sure we don't exceed input's allocated size/length
141
if (offset < 0 || len < 0 || (long)offset + len > input.length)
142             throw new ArrayIndexOutOfBoundsException JavaDoc();
143
144         // compute number of bytes still unhashed; ie. present in buffer
145
int bufferNdx = (int)(count % BLOCK_LENGTH);
146         count += len; // update number of bytes
147
int partLen = BLOCK_LENGTH - bufferNdx;
148         int i = 0;
149         if (len >= partLen) {
150             System.arraycopy(input, offset, buffer, bufferNdx, partLen);
151
152
153             transform(buffer, 0);
154
155             for (i = partLen; i + BLOCK_LENGTH - 1 < len; i+= BLOCK_LENGTH)
156                 transform(input, offset + i);
157             bufferNdx = 0;
158         }
159         // buffer remaining input
160
if (i < len)
161             System.arraycopy(input, offset + i, buffer, bufferNdx, len - i);
162     }
163
164     /**
165      * Completes the hash computation by performing final operations such
166      * as padding. At the return of this engineDigest, the MD engine is
167      * reset.
168      *
169      * @return the array of bytes for the resulting hash value.
170      */

171     public byte[] engineDigest () {
172         // pad output to 56 mod 64; as RFC1320 puts it: congruent to 448 mod 512
173
int bufferNdx = (int)(count % BLOCK_LENGTH);
174         int padLen = (bufferNdx < 56) ? (56 - bufferNdx) : (120 - bufferNdx);
175
176         // padding is alwas binary 1 followed by binary 0s
177
byte[] tail = new byte[padLen + 8];
178         tail[0] = (byte)0x80;
179
180         // append length before final transform:
181
// save number of bits, casting the long to an array of 8 bytes
182
// save low-order byte first.
183
for (int i = 0; i < 8; i++)
184             tail[padLen + i] = (byte)((count * 8) >>> (8 * i));
185
186         engineUpdate(tail, 0, tail.length);
187
188         byte[] result = new byte[16];
189         // cast this MD4's context (array of 4 ints) into an array of 16 bytes.
190
for (int i = 0; i < 4; i++)
191             for (int j = 0; j < 4; j++)
192                 result[i * 4 + j] = (byte)(context[i] >>> (8 * j));
193
194         // reset the engine
195
engineReset();
196         return result;
197     }
198
199
200 // own methods
201
//...........................................................................
202

203     /**
204      * MD4 basic transformation.
205      * <p>
206      * Transforms context based on 512 bits from input block starting
207      * from the offset'th byte.
208      *
209      * @param block input sub-array.
210      * @param offset starting position of sub-array.
211      */

212     private void transform (byte[] block, int offset) {
213
214         // encodes 64 bytes from input block into an array of 16 32-bit
215
// entities. Use A as a temp var.
216
for (int i = 0; i < 16; i++)
217             X[i] = (block[offset++] & 0xFF) |
218                    (block[offset++] & 0xFF) << 8 |
219                    (block[offset++] & 0xFF) << 16 |
220                    (block[offset++] & 0xFF) << 24;
221
222
223         int A = context[0];
224         int B = context[1];
225         int C = context[2];
226         int D = context[3];
227
228         A = FF(A, B, C, D, X[ 0], 3);
229         D = FF(D, A, B, C, X[ 1], 7);
230         C = FF(C, D, A, B, X[ 2], 11);
231         B = FF(B, C, D, A, X[ 3], 19);
232         A = FF(A, B, C, D, X[ 4], 3);
233         D = FF(D, A, B, C, X[ 5], 7);
234         C = FF(C, D, A, B, X[ 6], 11);
235         B = FF(B, C, D, A, X[ 7], 19);
236         A = FF(A, B, C, D, X[ 8], 3);
237         D = FF(D, A, B, C, X[ 9], 7);
238         C = FF(C, D, A, B, X[10], 11);
239         B = FF(B, C, D, A, X[11], 19);
240         A = FF(A, B, C, D, X[12], 3);
241         D = FF(D, A, B, C, X[13], 7);
242         C = FF(C, D, A, B, X[14], 11);
243         B = FF(B, C, D, A, X[15], 19);
244
245         A = GG(A, B, C, D, X[ 0], 3);
246         D = GG(D, A, B, C, X[ 4], 5);
247         C = GG(C, D, A, B, X[ 8], 9);
248         B = GG(B, C, D, A, X[12], 13);
249         A = GG(A, B, C, D, X[ 1], 3);
250         D = GG(D, A, B, C, X[ 5], 5);
251         C = GG(C, D, A, B, X[ 9], 9);
252         B = GG(B, C, D, A, X[13], 13);
253         A = GG(A, B, C, D, X[ 2], 3);
254         D = GG(D, A, B, C, X[ 6], 5);
255         C = GG(C, D, A, B, X[10], 9);
256         B = GG(B, C, D, A, X[14], 13);
257         A = GG(A, B, C, D, X[ 3], 3);
258         D = GG(D, A, B, C, X[ 7], 5);
259         C = GG(C, D, A, B, X[11], 9);
260         B = GG(B, C, D, A, X[15], 13);
261
262         A = HH(A, B, C, D, X[ 0], 3);
263         D = HH(D, A, B, C, X[ 8], 9);
264         C = HH(C, D, A, B, X[ 4], 11);
265         B = HH(B, C, D, A, X[12], 15);
266         A = HH(A, B, C, D, X[ 2], 3);
267         D = HH(D, A, B, C, X[10], 9);
268         C = HH(C, D, A, B, X[ 6], 11);
269         B = HH(B, C, D, A, X[14], 15);
270         A = HH(A, B, C, D, X[ 1], 3);
271         D = HH(D, A, B, C, X[ 9], 9);
272         C = HH(C, D, A, B, X[ 5], 11);
273         B = HH(B, C, D, A, X[13], 15);
274         A = HH(A, B, C, D, X[ 3], 3);
275         D = HH(D, A, B, C, X[11], 9);
276         C = HH(C, D, A, B, X[ 7], 11);
277         B = HH(B, C, D, A, X[15], 15);
278
279         context[0] += A;
280         context[1] += B;
281         context[2] += C;
282         context[3] += D;
283     }
284
285     // The basic MD4 atomic functions.
286

287     private int FF (int a, int b, int c, int d, int x, int s) {
288         int t = a + ((b & c) | (~b & d)) + x;
289         return t << s | t >>> (32 - s);
290     }
291     private int GG (int a, int b, int c, int d, int x, int s) {
292         int t = a + ((b & (c | d)) | (c & d)) + x + 0x5A827999;
293         return t << s | t >>> (32 - s);
294     }
295     private int HH (int a, int b, int c, int d, int x, int s) {
296         int t = a + (b ^ c ^ d) + x + 0x6ED9EBA1;
297         return t << s | t >>> (32 - s);
298     }
299 }
300
Popular Tags