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