KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > knowgate > 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.1.1.1 2005/06/23 15:16:09 smontoro
5
// hipergate backend
6
//
7
// Revision 1.2 1998/01/05 03:41:19 iang
8
// Added references only.
9
//
10
// Revision 1.1.1.1 1997/11/03 22:36:56 hopwood
11
// + Imported to CVS (tagged as 'start').
12
//
13
// Revision 0.1.0.0 1997/07/14 R. Naffah
14
// + original version
15
//
16
// $Endlog$
17
/*
18  * Copyright (c) 1997 Systemics Ltd
19  * on behalf of the Cryptix Development Team. All rights reserved.
20  */

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

40 public class MD4 extends MessageDigest JavaDoc implements Cloneable JavaDoc
41 {
42 // MD4 specific object variables
43
//...........................................................................
44

45     /**
46      * The size in bytes of the input block to the tranformation algorithm.
47      */

48     private static final int BLOCK_LENGTH = 64; // = 512 / 8;
49

50     /**
51      * 4 32-bit words (interim result)
52      */

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

58     private long count;
59
60     /**
61      * 512 bits input buffer = 16 x 32-bit words holds until reaches 512 bits.
62      */

63     private byte[] buffer = new byte[BLOCK_LENGTH];
64
65     /**
66      * 512 bits work buffer = 16 x 32-bit words
67      */

68     private int[] X = new int[16];
69
70
71 // Constructors
72
//...........................................................................
73

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

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

93     /**
94      * Returns a copy of this MD object.
95      */

96     public Object JavaDoc clone() { return new MD4(this); }
97
98
99 // JCE methods
100
//...........................................................................
101

102     /**
103      * Resets this object disregarding any temporary data present at the
104      * time of the invocation of this call.
105      */

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

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

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

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

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

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

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