View Javadoc
1   package com.jsql.util.bruter;
2   
3   // This file is currently unlocked (change this line if you lock the file)
4   //
5   // $Log: MD4.java,v $
6   // Revision 1.2  1998/01/05 03:41:19  iang
7   // Added references only.
8   //
9   // Revision 1.1.1.1  1997/11/03 22:36:56  hopwood
10  // + Imported to CVS (tagged as 'start').
11  //
12  // Revision 0.1.0.0  1997/07/14  R. Naffah
13  // + original version
14  //
15  // $Endlog$
16  /*
17   * Copyright (c) 1997 Systemics Ltd
18   * on behalf of the Cryptix Development Team.  All rights reserved.
19   */
20  
21  import java.security.MessageDigest;
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 DigestMD4 extends MessageDigest implements Cloneable {
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 final int[] X = new int[16];
66  
67  
68      // Constructors
69      //...........................................................................
70  
71      public DigestMD4() {
72          
73          super("MD4");
74          this.engineReset();
75      }
76  
77      /**
78       *    This constructor is here to implement cloneability of this class.
79       */
80      private DigestMD4(DigestMD4 md) {
81          
82          this();
83          this.context = md.context.clone();
84          this.buffer = md.buffer.clone();
85          this.count = md.count;
86      }
87  
88  
89      // Cloneable method implementation
90      //...........................................................................
91  
92      /**
93       * Returns a copy of this MD object.
94       */
95      @Override
96      public Object clone() throws CloneNotSupportedException {
97  
98          Object clone = super.clone();
99          return new DigestMD4(this);
100     }
101 
102 
103     // JCE methods
104     //...........................................................................
105 
106     /**
107      * Resets this object disregarding any temporary data present at the
108      * time of the invocation of this call.
109      */
110     @Override
111     public void engineReset() {
112         
113         // initial values of MD4 i.e. A, B, C, D
114         // as per rfc-1320; they are low-order byte first
115         this.context[0] = 0x67452301;
116         this.context[1] = 0xEFCDAB89;
117         this.context[2] = 0x98BADCFE;
118         this.context[3] = 0x10325476;
119         this.count = 0L;
120         
121         for (int i = 0; i < BLOCK_LENGTH; i++) {
122             this.buffer[i] = 0;
123         }
124     }
125 
126     /**
127      * Continues an MD4 message digest using the input byte.
128      */
129     @Override
130     public void engineUpdate(byte b) {
131         
132         // compute number of bytes still unhashed; ie. present in buffer
133         int i = (int)(this.count % BLOCK_LENGTH);
134         this.count++;                                        // update number of bytes
135         this.buffer[i] = b;
136         
137         if (i == BLOCK_LENGTH - 1) {
138             this.transform(this.buffer, 0);
139         }
140     }
141 
142     /**
143      * MD4 block update operation.
144      * <p>
145      * Continues an MD4 message digest operation, by filling the buffer,
146      * transform(ing) data in 512-bit message block(s), updating the variables
147      * context and count, and leaving (buffering) the remaining bytes in buffer
148      * for the next update or finish.
149      *
150      * @param    input    input block
151      * @param    offset    start of meaningful bytes in input
152      * @param    len        count of bytes in input block to consider
153      */
154     @Override
155     public void engineUpdate(byte[] input, int offset, int len) {
156         
157         // make sure we don't exceed input's allocated size/length
158         if (offset < 0 || len < 0 || (long)offset + len > input.length) {
159             throw new ArrayIndexOutOfBoundsException();
160         }
161         
162         // compute number of bytes still unhashed; ie. present in buffer
163         int bufferNdx = (int)(this.count % BLOCK_LENGTH);
164         this.count += len;                                        // update number of bytes
165         int partLen = BLOCK_LENGTH - bufferNdx;
166         int i = 0;
167         
168         if (len >= partLen) {
169             
170             System.arraycopy(input, offset, this.buffer, bufferNdx, partLen);
171 
172             this.transform(this.buffer, 0);
173 
174             for (i = partLen; i + BLOCK_LENGTH - 1 < len; i+= BLOCK_LENGTH) {
175                 this.transform(input, offset + i);
176             }
177             
178             bufferNdx = 0;
179         }
180         
181         // buffer remaining input
182         if (i < len) {
183             System.arraycopy(input, offset + i, this.buffer, bufferNdx, len - i);
184         }
185     }
186 
187     /**
188      * Completes the hash computation by performing final operations such
189      * as padding. At the return of this engineDigest, the MD engine is
190      * reset.
191      *
192      * @return the array of bytes for the resulting hash value.
193      */
194     @Override
195     public byte[] engineDigest() {
196         
197         // pad output to 56 mod 64; as RFC1320 puts it: congruent to 448 mod 512
198         int bufferNdx = (int)(this.count % BLOCK_LENGTH);
199         int padLen = bufferNdx < 56 ? 56 - bufferNdx : 120 - bufferNdx;
200 
201         // padding is alwas binary 1 followed by binary 0s
202         byte[] tail = new byte[padLen + 8];
203         tail[0] = (byte)0x80;
204 
205         // append length before final transform:
206         // save number of bits, casting the long to an array of 8 bytes
207         // save low-order byte first.
208         for (int i = 0; i < 8; i++) {
209             tail[padLen + i] = (byte)((this.count * 8) >>> (8 * i));
210         }
211         
212         this.engineUpdate(tail, 0, tail.length);
213 
214         byte[] result = new byte[16];
215         
216         // cast this MD4's context (array of 4 ints) into an array of 16 bytes.
217         for (int i = 0; i < 4; i++) {
218             for (int j = 0; j < 4; j++) {
219                 result[i * 4 + j] = (byte)(this.context[i] >>> (8 * j));
220             }
221         }
222     
223         // reset the engine
224         this.engineReset();
225         
226         return result;
227     }
228 
229 
230     // own methods
231     //...........................................................................
232 
233     /**
234      *    MD4 basic transformation.
235      *    <p>
236      *    Transforms context based on 512 bits from input block starting
237      *    from the offset'th byte.
238      *
239      *    @param    block    input sub-array.
240      *    @param    offset    starting position of sub-array.
241      */
242     private void transform(byte[] block, int offset) {
243 
244         // encodes 64 bytes from input block into an array of 16 32-bit
245         // entities. Use A as a temp var.
246         for (int i = 0; i < 16; i++) {
247             this.X[i] =
248                 (block[offset++] & 0xFF)
249                 | (block[offset++] & 0xFF) <<  8
250                 | (block[offset++] & 0xFF) << 16
251                 | (block[offset++] & 0xFF) << 24;
252         }
253 
254         int A = this.context[0];
255         int B = this.context[1];
256         int C = this.context[2];
257         int D = this.context[3];
258 
259         A = this.FF(A, B, C, D, this.X[ 0],  3);
260         D = this.FF(D, A, B, C, this.X[ 1],  7);
261         C = this.FF(C, D, A, B, this.X[ 2], 11);
262         B = this.FF(B, C, D, A, this.X[ 3], 19);
263         A = this.FF(A, B, C, D, this.X[ 4],  3);
264         D = this.FF(D, A, B, C, this.X[ 5],  7);
265         C = this.FF(C, D, A, B, this.X[ 6], 11);
266         B = this.FF(B, C, D, A, this.X[ 7], 19);
267         A = this.FF(A, B, C, D, this.X[ 8],  3);
268         D = this.FF(D, A, B, C, this.X[ 9],  7);
269         C = this.FF(C, D, A, B, this.X[10], 11);
270         B = this.FF(B, C, D, A, this.X[11], 19);
271         A = this.FF(A, B, C, D, this.X[12],  3);
272         D = this.FF(D, A, B, C, this.X[13],  7);
273         C = this.FF(C, D, A, B, this.X[14], 11);
274         B = this.FF(B, C, D, A, this.X[15], 19);
275 
276         A = this.GG(A, B, C, D, this.X[ 0],  3);
277         D = this.GG(D, A, B, C, this.X[ 4],  5);
278         C = this.GG(C, D, A, B, this.X[ 8],  9);
279         B = this.GG(B, C, D, A, this.X[12], 13);
280         A = this.GG(A, B, C, D, this.X[ 1],  3);
281         D = this.GG(D, A, B, C, this.X[ 5],  5);
282         C = this.GG(C, D, A, B, this.X[ 9],  9);
283         B = this.GG(B, C, D, A, this.X[13], 13);
284         A = this.GG(A, B, C, D, this.X[ 2],  3);
285         D = this.GG(D, A, B, C, this.X[ 6],  5);
286         C = this.GG(C, D, A, B, this.X[10],  9);
287         B = this.GG(B, C, D, A, this.X[14], 13);
288         A = this.GG(A, B, C, D, this.X[ 3],  3);
289         D = this.GG(D, A, B, C, this.X[ 7],  5);
290         C = this.GG(C, D, A, B, this.X[11],  9);
291         B = this.GG(B, C, D, A, this.X[15], 13);
292 
293         A = this.HH(A, B, C, D, this.X[ 0],  3);
294         D = this.HH(D, A, B, C, this.X[ 8],  9);
295         C = this.HH(C, D, A, B, this.X[ 4], 11);
296         B = this.HH(B, C, D, A, this.X[12], 15);
297         A = this.HH(A, B, C, D, this.X[ 2],  3);
298         D = this.HH(D, A, B, C, this.X[10],  9);
299         C = this.HH(C, D, A, B, this.X[ 6], 11);
300         B = this.HH(B, C, D, A, this.X[14], 15);
301         A = this.HH(A, B, C, D, this.X[ 1],  3);
302         D = this.HH(D, A, B, C, this.X[ 9],  9);
303         C = this.HH(C, D, A, B, this.X[ 5], 11);
304         B = this.HH(B, C, D, A, this.X[13], 15);
305         A = this.HH(A, B, C, D, this.X[ 3],  3);
306         D = this.HH(D, A, B, C, this.X[11],  9);
307         C = this.HH(C, D, A, B, this.X[ 7], 11);
308         B = this.HH(B, C, D, A, this.X[15], 15);
309 
310         this.context[0] += A;
311         this.context[1] += B;
312         this.context[2] += C;
313         this.context[3] += D;
314     }
315 
316     // The basic MD4 atomic functions.
317 
318     private int FF(int a, int b, int c, int d, int x, int s) {
319         
320         int t = a + ((b & c) | (~b & d)) + x;
321         return t << s | t >>> (32 - s);
322     }
323     
324     private int GG(int a, int b, int c, int d, int x, int s) {
325         
326         int t = a + ((b & (c | d)) | (c & d)) + x + 0x5A827999;
327         return t << s | t >>> (32 - s);
328     }
329     
330     private int HH(int a, int b, int c, int d, int x, int s) {
331         
332         int t = a + (b ^ c ^ d) + x + 0x6ED9EBA1;
333         return t << s | t >>> (32 - s);
334     }
335 }