1   /* $RCSfile: RIPEMD160MessageDigestImpl.java,v $
2    * $Revision: 1.2 $
3    * $Date: 2002/02/17 08:27:00 $
4    * $Author: uwe $
5    * $State: Exp $
6    *
7    * Created on July 4, 2001, 1:01 PM
8    *
9    * Copyright (C) 2001 Uwe Guenther <uwe@cscc.de>
10   *
11   * This file is part of the jhbci JCE-ServiceProvider. The jhbci JCE-
12   * ServiceProvider is a library, written in JavaTM, that should be 
13   * used in HBCI banking applications (clients and may be servers),
14   * to do cryptographic operations.
15   *
16   * The jhbci library is free software; you can redistribute it and/or
17   * modify it under the terms of the GNU Lesser General Public
18   * License as published by the Free Software Foundation; either
19   * version 2.1 of the License, or (at your option) any later version.
20   *
21   * The jhbci library is distributed in the hope that it will be useful,
22   * but WITHOUT ANY WARRANTY; without even the implied warranty of
23   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24   * Lesser General Public License for more details.
25   *
26   * You should have received a copy of the GNU Lesser General Public
27   * License along with this library; if not, write to the Free Software
28   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29   *
30   */
31  
32  package de.cscc.crypto.provider;
33  
34  import java.security.DigestException;
35  
36  /** 
37   * This class contains the RIPEMD-160 algorithm. It is a helper class for 
38   * ServiceProvider engines. You can not instance these class only at 
39   * package scope and you can not inherit from these final class.
40   * These class is directly used by ServiceProviders from these package,
41   * such as RIPEMD160Engine.
42   *
43   * <p>The sum of all bytes, added with {@link #update(byte)
44   * update(byte)} and {@link #update(byte[], int, int) 
45   * update(byte[], int, int)} are processed by the RIPEMD-160
46   * message digest algorithm with {@link #digest() digest()} or
47   * {@link #digest(byte[] , int, int) digest(byte[], int, int)}.
48   *
49   * <pre>
50   *
51   * How does it work:
52   * =================
53   *
54   * RIPEMD-160 works only with whole 512 bit Blocks.
55   *
56   *        512 bits == 64 Bytes == 16 Words
57   * -------------------------------------------------
58   * |00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
59   * -------------------------------------------------
60   *                    /  \
61   *                   /    \
62   *                  /      \
63   *                 /        \
64   *                /          \
65   *               -------------
66   *               |32 bit Word|   <-- 32 bit Word = 4 Byte
67   *               -------------
68   *               |00|01|02|03|   <-- 4 Bytes = 4 x 8 bit = 32 bit
69   *               -------------
70   *
71   * </pre>
72   *
73   * @author  <a href=mailto:uwe@cscc.de>Uwe G&uuml;nther</a>
74   * @version $Revision: 1.2 $
75   */
76  final class RIPEMD160MessageDigestImpl implements Cloneable {
77      
78      /** The length of the message digest in byte. */
79      private static final int DIGEST_LENGTH = 20; // 20 byte or 160 bit
80      
81      /** Counts the bytes of the whole message that will be digested. */                    
82      private RIPEMD160ByteCounter byteCounter;
83      
84      /** Internal <CODE>byteBuffer</CODE>. */
85      private RIPEMD160ByteBuffer byteBuffer;
86      
87      /** 
88       * Internal wordBuffer that holds a 512 bit message block
89       * 512 bit are the block size for the RIPEMD160 algorithm
90       * that will be compressed if the compress functions runs at ones.
91       */
92      private RIPEMD160WordBuffer wordBuffer;
93      
94      /**
95       * Internal messageDigest repesentation object for the 
96       * five MD words == 160 bit or 20 Byte.
97       */
98      private RIPEMD160MessageDigestBuffer messageDigest;
99      
100     /** Creates new RIPEMD160MessageDigestImpl. */
101     public RIPEMD160MessageDigestImpl() {
102         this.byteCounter   =new RIPEMD160ByteCounter();
103         this.byteBuffer    =new RIPEMD160ByteBuffer();
104         this.wordBuffer    =new RIPEMD160WordBuffer();
105         this.messageDigest =new RIPEMD160MessageDigestBuffer();
106     }
107     
108     /** 
109      * Creates and returns a deep copy of this object.
110      * @return a clone of this instance.
111      * @see java.lang.Cloneable
112      * @exception CloneNotSupportedException if the object's class does not
113      *             support the <code>Cloneable</code> interface. Subclasses
114      *             that override the <code>clone</code> method can also
115      *             throw this exception to indicate that an instance cannot
116      *             be cloned.
117      */
118     public Object clone() throws CloneNotSupportedException {
119         RIPEMD160MessageDigestImpl result = 
120         (RIPEMD160MessageDigestImpl) super.clone();
121         result.byteCounter = (RIPEMD160ByteCounter) this.byteCounter.clone();
122         result.byteBuffer = (RIPEMD160ByteBuffer) this.byteBuffer.clone();
123         result.wordBuffer = (RIPEMD160WordBuffer) this.wordBuffer.clone();
124         result.messageDigest = 
125                 (RIPEMD160MessageDigestBuffer) this.messageDigest.clone();
126         return result;
127     }        
128     
129     /** 
130      * Compares two RIPEMD160MessageDigestImpl object. If the private members
131      * of obj are equal with the private members of this object the method
132      * will return true, otherwise false.
133      *
134      * @return return true if the objects are deeply equal.
135      * @param obj RIPEMD160MessageDigestImpl object to compare.
136      */
137     public boolean equals(Object obj){
138         //Only for performance.
139         if (this == obj) {
140             return true;
141         } 
142         
143         //If obj == null then instanceof returns false, see JLS 15.20.2
144         if (!(obj instanceof RIPEMD160MessageDigestImpl)) {            
145             return false;
146         }
147             
148         RIPEMD160MessageDigestImpl other = (RIPEMD160MessageDigestImpl) obj;
149         return this.byteCounter.equals(other.byteCounter)     &&     
150                this.byteBuffer.equals(other.byteBuffer)       &&
151                this.wordBuffer.equals(other.wordBuffer)       &&
152                this.messageDigest.equals(other.messageDigest)  ;
153     }
154     
155     /** 
156      * Returns a hash code value for the object. This method is
157      * supported for the benefit of hashtables such as those provided by
158      * <code>java.util.Hashtable</code>.
159      *
160      * @return  a hash code value for this object.
161      * @see     #equals(java.lang.Object)
162      * @see     java.util.Hashtable
163      */
164     public int hashCode() {
165         int result = 17;
166         result = 37*result + this.byteCounter.hashCode();
167         result = 37*result + this.byteBuffer.hashCode();
168         result = 37*result + this.wordBuffer.hashCode();
169         result = 37*result + this.messageDigest.hashCode();
170         return result;
171     }        
172     
173     /** 
174      * Returns a string representation of the object. 
175      * @return  a string representation of the object.
176      */
177     public String toString() 
178     {
179         String returnValue =""; 
180         returnValue += "<MessageDigestBuffer: " + this.messageDigest + ">";
181         returnValue += "<WordBuffer:  " + this.wordBuffer + ">";
182         returnValue += "<ByteCounter: " + this.byteCounter + ">";
183         returnValue += "<ByteBuffer: " + this.byteBuffer + ">";        
184         return returnValue;
185     }     
186     
187     /**
188      * If the whole message added to the message digest object, you should 
189      * invoke these method. Returns the 160 bit RIPEMD-160 digest as a byte
190      * array (20 Byte or 160 bit).
191      *
192      * @return the message digest in 20 byte long byte array.
193      * This byte array homes the 160 bit digest in binary form.
194      */
195     public byte[] digest() {
196         
197         /* Save the length of the message in bit in long finalBitLength
198          * finalBitLength = ByteCounter * 2^3
199          *
200          * or
201          *
202          * finalBitLength = byteCounter * 8
203          *
204          * After these point any values of this.byteCounter are obsolete!!!
205          */
206         byteCounter.setFinalBitLength();
207         
208         /* Message Padding:
209          * 1. We insert an 1 bit at the Message End.
210          *    We do this in Byte Form, 0b10000000 == 0x80 == 128
211          *
212          */
213         update((byte)0x80);
214         
215         /* Message Padding:
216          * 2. While to byteBuffer is not empty, we will fill it with 0x00 Bytes
217          *    until it is full. And if it is full the byteBuffer is flushed to
218          *    empty if it was full from the update method and isNotEmpty() is 
219          *    false and the loop finishs.
220          *
221          */
222         while(this.byteBuffer.isNotEmpty()) {
223             update((byte)0x00);
224         }
225         
226         
227         /* Check if there are two or more than two words free in the wordBuffer
228          * to do final Padding. If not we process the word Buffer and do the 
229          * final Padding in the next 512 bit Block.
230          */
231         if (this.wordBuffer.areLessThanTwoWordsFree()) {
232             processWordBuffer();
233         }
234         
235         
236         /* Do final Padding at the 512 bit message block (wordBuffer)
237          *
238          *
239          */
240         this.wordBuffer.doFinalPadding(byteCounter.getFinalBitLength());
241         
242         /* This is the final call of the RIPEMD-160 Algo (compress funktion),
243          * because the message is padded an the finalBitLength is inserted
244          *in the last two words of the wordBuffer
245          *
246          */
247         processWordBuffer();
248         
249         return messageDigest.toByteBuffer();
250     }
251     
252     /**
253      * If the whole message added to the message digest object, you should 
254      * invoke these method. Returns the 160 bit RIPEMD-160 digest at a byte
255      * array (20 Byte or 160 bit ).
256      *
257      * @param buf the message digest in 20 byte long byte array.
258      * This byte array contains the 160 bit digest in binary form.
259      * @param offset begin of buffer
260      * @param len end of buffer
261      * @throws DigestException if the difference between len-offset less than
262      * 20 bytes a DigestException will be thrown.
263      * @return the length of the digest stored in the output buffer
264      */
265     public int digest(byte[] buf, int offset, int len) 
266     throws DigestException {
267        
268         /* The following two conditions are checked through the 
269          * java.security.MessageDigest API, so we do not 
270          * check they here:
271          *
272          * (buf.length < DIGEST_LENGTH) 
273          * (offset + len > buf.length)      
274          *
275          * Should be the Sun API changed you should add these two conditions
276          * to the if with the || operator.
277          */
278         if (len < RIPEMD160MessageDigestImpl.DIGEST_LENGTH) {
279             throw new DigestException("Buffer to less. It should be " +
280                     RIPEMD160MessageDigestImpl.DIGEST_LENGTH + "." );
281         }
282 
283         System.arraycopy(digest(), 0, buf, offset,
284             RIPEMD160MessageDigestImpl.DIGEST_LENGTH);
285         
286         return RIPEMD160MessageDigestImpl.DIGEST_LENGTH;
287     }
288     
289     /**
290      * Returns the length of the message digest in byte. In case of RIPEMD-160
291      * it will be 20.
292      * @return digest length (20)
293      */
294     public int getDigestLength() {
295         return RIPEMD160MessageDigestImpl.DIGEST_LENGTH;
296     }
297     
298     /**
299      * Resets the RIPEMD160MessageDigestImpl object, for further use. So if you 
300      * have calculated your digest, you should invoke reset() to reset this 
301      * digest object to calculate a new digest from a new message.
302      */
303     public void reset() {
304         this.byteCounter.reset();
305         this.byteBuffer.reset();
306         this.wordBuffer.reset();
307         this.messageDigest.init(); // set the initial values h0, h1, h2, h3, h4
308     }
309     
310     /**
311      * Updates the internal message buffer (byteBuffer and wordBuffer) with 
312      * value.
313      *
314      * @param value message byte.
315      */
316     public void update(byte value) {
317 
318         this.byteBuffer.set(value);
319         
320         //this.byteCounter++;
321         this.byteCounter.inc();
322         
323         if (this.byteBuffer.isFull()) {
324             processByteBuffer(); // and reset it [this.byteBuffer.reset();]
325         }
326     }
327     
328     /**
329      * Updates the internal message buffer with <CODE>byte[] value</CODE>,
330      * starting at offset, ending at len.
331      * @param values message byte array.
332      * @param offset begin of message byte array.
333      * @param len end of message byte array.
334      */
335     public void update(byte[] values, int offset, int len) {
336         
337         for (int i = offset; i < offset+len; i++) {
338             update(values[i]);
339         }
340     }
341       
342     /** 
343      * In this method the internal byteBuffer is moved with little endian 
344      * byte order to next free word in the internal wordBuffer[16]. If move
345      * finished <CODE>byteBuffer.reset()</CODE> is called to reset byteBuffer.
346      */
347     private void processByteBuffer() {
348         
349         this.wordBuffer.set(this.byteBuffer.toWord());
350         
351         /* Oure wordBuffer is full, now we should process the compress
352          * RIPEMD-160 compress-Algo located in processWordBuffer.
353          *
354          * There will the wordBuffer be flushed with 0s (Zeros) and the
355          * compressed result will be put in the 5 messageDigest 32-bit Words!
356          */
357         if (this.wordBuffer.isFull()) {
358             processWordBuffer();
359         }
360 
361         /**  Reset the byteBuffer after processing
362          */
363         this.byteBuffer.reset();  
364     }
365     
366     /**
367      * Functions F,G,H,I,J are the five non linear functions at bit level:
368      * exor, mux, -, mux, -
369      *
370      * used in left  round 1 (0  <= j <= 15); right round 5 (64 <= j <= 79)
371      * @param inX algorithm.
372      * @param inY algorithm.
373      * @param inZ algorithm.
374      * @return algorithm.
375      */
376    private static int operationF(int inX, int inY, int inZ) {
377         return inX ^ inY ^ inZ;
378     }
379 
380     /**
381      * Nonlinear functions at bit level: exor, mux, -, mux, -
382      * used in left  round 2 (16 <= j <= 31); right round 4 (48 <= j <= 63).
383      *
384      * @param inX algorithm.
385      * @param inY algorithm.
386      * @param inZ algorithm.
387      * @return algorithm.
388      */
389     private static int operationG(int inX, int inY, int inZ) {
390         return (inX & inY) | (~inX & inZ);
391     }
392     
393     /**
394      * Non linear functions at bit level: exor, mux, -, mux, -
395      * used in left  round 3 (32 <= j <= 47); right round 3 (32 <= j <= 47).
396      *
397      * @param inX algorithm.
398      * @param inY algorithm.
399      * @param inZ algorithm.
400      * @return algorithm.
401      */
402     private static int operationH(int inX, int inY, int inZ) {
403         return (inX | ~inY) ^ inZ;
404     }
405 
406     /**
407      * Non linear functions at bit level: exor, mux, -, mux, -
408      * used in left  round 4 (48 <= j <= 63); right round 2 (16 <= j <= 31).
409      *
410      * @param inX algorithm.
411      * @param inY algorithm.
412      * @param inZ algorithm.
413      * @return algorithm.
414      */
415     private static int operationI(int inX, int inY, int inZ) {
416         return (inX & inZ) | (inY & ~inZ);
417     }
418 
419     /**
420      * Non linear functions at bit level: exor, mux, -, mux, - 
421      * used in left  round 5 (64 <= j <= 79); right round 2  (0 <= j <= 15).
422      * @param inX algorithm.
423      * @param inY algorithm.
424      * @param inZ algorithm.
425      * @return algorithm.
426      */
427     private static int operationJ(int inX, int inY, int inZ) {
428         return inX ^ (inY | ~inZ);
429     }
430     
431     /**
432      * rotateOverLeft() rotate left Funktion (cyclic rotate left).
433      *
434      * <pre>
435      * We rotate the bits in a left order:
436      *
437      * 1. We shift the bits in the original x n positions to the left side
438      *    with: x << n
439      * 2. We shift the bits in the original x 32-n positions to te right side.
440      *    These are the bits, that we shift out in Step 1. We do that
441      *    with: x >>> n
442      *    The >>>  right shift operator fills the free positions at the left
443      *    side with 0 (Zero). E.g. x >>> 5 shift the bits at 5 positions to the
444      *    right side and fills the 5 leftmost positions with 0 (Zero):
445      *
446      *    0b10101010101010101010101010101010   >>> 5  ==
447      *      --------------------------->>>>>   // >>>>> means cating these
448      *                                         // five bits!
449      *    0b00000101010101010101010101010101
450      *      ^^^^^----------------------------  // ^^^^^^ means filling these
451      *                                         // five free positions with 0
452      *                                         // (Zero)!
453      *
454      *    The operator >>> is necessary since we don't have unsigned numeric
455      *    types in Java.
456      *
457      *    If we would do that with the >> shift operator the fill bit is
458      *    dependend from the sign bit (the left most bit). E.g x >> 5 shift the
459      *    bits at 5 positions to the right side and fills the 5 leftmost
460      *    positions with 0 (Zero):
461      *
462      *    0b01010101010101010101010101010101   >> 5  ==
463      *      --------------------------->>>>>   // >>>>> means cating these
464      *                                         //five bits!
465      *    0b000000101010101010101010101010101
466      *      ^^^^^----------------------------  // ^^^^^^ means filling these
467      *                                         // five free positions with 0
468      *                                         // (Zero)! Because the leftmost
469      *                                         // bit (sign-bit) is not set
470      *                                         // (is set to 0)
471      *
472      *   0b10101010101010101010101010101010   >> 5  ==
473      *     --------------------------->>>>>   // >>>>> means cating these
474      *                                        // five bits!
475      *   0b11111101010101010101010101010101
476      *     ^^^^^----------------------------  // ^^^^^^ means filling these
477      *                                        // five free Positions with 1
478      *                                        // (One)! Because the leftmost bit
479      *                                        // (sign-bit) is set (is set to 1)
480      *
481      * 3. Now we link the value from step one the value from step two together
482      *    with a logical OR (|). These means our int is now organized as a ring
483      *    buffer. The n leftmost bits that we lost in step one are shiftet in
484      *    the right side with step two and three. E.g. (x << 5) | (x >>> (32-5))
485      *
486      *    a. 0b11110000111100001111000011110000  <<  5  ==
487      *                                        0b00011110000111100001111000000000
488      *
489      *    b. 0b11110000111100001111000011110000  >>> 27 ==
490      *                                        0b00000000000000000000000000011110
491      *                                        ----------------------------------
492      *                              a | b  == 0b00011110000111100001111000011110
493      * </pre>
494      * @param in 32 bit word who will be cyclic left shifted.
495      * @param shift shift value.
496      * @return the shifted 32 bit word.
497      */
498     private static int rotateOverLeft(int in, int shift){
499         return (in << shift) | (in >>> (32-shift));
500     }
501 
502     /** 
503      * This is the compress method for a 512 bit block
504      * 512 bit == 16 32-bit-words or 60 bytes.
505      *
506      * This is the really RIPEMD-160 algorithm. We process the wordBuffer[16]
507      * and put the result in the MDbuf[5] (five 32 bit words) for further use
508      * through this method.
509      *
510      * There are always five rounds for the left side and five round for the
511      * right side of the RIPEMD-160 Algo. Each round contains 16 steps, wich
512      * are computed through the non linear methodes at bit level operationF(), 
513      * operationG(), operationH(), operationI() and operationJ(). The five
514      * rounds on each side are independent of the rounds
515      * of the other side until after round five at each side. There will the
516      * results computed and putted in the MDbuf[5] word registers.
517      */
518     private void processWordBuffer() {
519 
520         int aa = this.messageDigest.getAt(0);
521         int bb = this.messageDigest.getAt(1);
522         int cc = this.messageDigest.getAt(2);
523         int dd = this.messageDigest.getAt(3);
524         int ee = this.messageDigest.getAt(4);
525         
526         int aaa = this.messageDigest.getAt(0);
527         int bbb = this.messageDigest.getAt(1);
528         int ccc = this.messageDigest.getAt(2);
529         int ddd = this.messageDigest.getAt(3);
530         int eee = this.messageDigest.getAt(4);
531         
532         
533         /*
534          * Left Side Processing
535          * Round 1, Steps 0-15
536          *
537          */
538         aa = rotateOverLeft(aa + operationF(bb,cc,dd) + this.wordBuffer.getAt( 0), 11) + ee;
539         cc = rotateOverLeft(cc, 10);
540         
541         ee = rotateOverLeft(ee + operationF(aa,bb,cc) + this.wordBuffer.getAt( 1), 14) + dd;
542         bb = rotateOverLeft(bb, 10);
543         
544         dd = rotateOverLeft(dd + operationF(ee,aa,bb) + this.wordBuffer.getAt( 2), 15) + cc;
545         aa = rotateOverLeft(aa, 10);
546         
547         cc = rotateOverLeft(cc + operationF(dd,ee,aa) + this.wordBuffer.getAt( 3), 12) + bb;
548         ee = rotateOverLeft(ee, 10);
549         
550         bb = rotateOverLeft(bb + operationF(cc,dd,ee) + this.wordBuffer.getAt( 4),  5) + aa;
551         dd = rotateOverLeft(dd, 10);
552         
553         aa = rotateOverLeft(aa + operationF(bb,cc,dd) + this.wordBuffer.getAt( 5),  8) + ee;
554         cc = rotateOverLeft(cc, 10);
555         
556         ee = rotateOverLeft(ee + operationF(aa,bb,cc) + this.wordBuffer.getAt( 6),  7) + dd;
557         bb = rotateOverLeft(bb, 10);
558         
559         dd = rotateOverLeft(dd + operationF(ee,aa,bb) + this.wordBuffer.getAt( 7),  9) + cc;
560         aa = rotateOverLeft(aa, 10);
561         
562         cc = rotateOverLeft(cc + operationF(dd,ee,aa) + this.wordBuffer.getAt( 8), 11) + bb;
563         ee = rotateOverLeft(ee, 10);
564         
565         bb = rotateOverLeft(bb + operationF(cc,dd,ee) + this.wordBuffer.getAt( 9), 13) + aa;
566         dd = rotateOverLeft(dd, 10);
567         
568         aa = rotateOverLeft(aa + operationF(bb,cc,dd) + this.wordBuffer.getAt(10), 14) + ee;
569         cc = rotateOverLeft(cc, 10);
570         
571         ee = rotateOverLeft(ee + operationF(aa,bb,cc) + this.wordBuffer.getAt(11), 15) + dd;
572         bb = rotateOverLeft(bb, 10);
573         
574         dd = rotateOverLeft(dd + operationF(ee,aa,bb) + this.wordBuffer.getAt(12),  6) + cc;
575         aa = rotateOverLeft(aa, 10);
576         
577         cc = rotateOverLeft(cc + operationF(dd,ee,aa) + this.wordBuffer.getAt(13),  7) + bb;
578         ee = rotateOverLeft(ee, 10);
579         
580         bb = rotateOverLeft(bb + operationF(cc,dd,ee) + this.wordBuffer.getAt(14),  9) + aa;
581         dd = rotateOverLeft(dd, 10);
582         
583         aa = rotateOverLeft(aa + operationF(bb,cc,dd) + this.wordBuffer.getAt(15),  8) + ee;
584         cc = rotateOverLeft(cc, 10);
585         
586         
587         /*
588          * Left Side Processing
589          * Round 2, Steps 16-31
590          *
591          */
592         ee = rotateOverLeft(ee + operationG(aa,bb,cc) + this.wordBuffer.getAt( 7) + 0x5a827999,  7) + dd;
593         bb = rotateOverLeft(bb, 10);
594         
595         dd = rotateOverLeft(dd + operationG(ee,aa,bb) + this.wordBuffer.getAt( 4) + 0x5a827999,  6) + cc;
596         aa = rotateOverLeft(aa, 10);
597         
598         cc = rotateOverLeft(cc + operationG(dd,ee,aa) + this.wordBuffer.getAt(13) + 0x5a827999,  8) + bb;
599         ee = rotateOverLeft(ee, 10);
600         
601         bb = rotateOverLeft(bb + operationG(cc,dd,ee) + this.wordBuffer.getAt( 1) + 0x5a827999, 13) + aa;
602         dd = rotateOverLeft(dd, 10);
603         
604         aa = rotateOverLeft(aa + operationG(bb,cc,dd) + this.wordBuffer.getAt(10) + 0x5a827999, 11) + ee;
605         cc = rotateOverLeft(cc, 10);
606         
607         ee = rotateOverLeft(ee + operationG(aa,bb,cc) + this.wordBuffer.getAt( 6) + 0x5a827999,  9) + dd;
608         bb = rotateOverLeft(bb, 10);
609         
610         dd = rotateOverLeft(dd + operationG(ee,aa,bb) + this.wordBuffer.getAt(15) + 0x5a827999,  7) + cc;
611         aa = rotateOverLeft(aa, 10);
612         
613         cc = rotateOverLeft(cc + operationG(dd,ee,aa) + this.wordBuffer.getAt( 3) + 0x5a827999, 15) + bb;
614         ee = rotateOverLeft(ee, 10);
615         
616         bb = rotateOverLeft(bb + operationG(cc,dd,ee) + this.wordBuffer.getAt(12) + 0x5a827999,  7) + aa;
617         dd = rotateOverLeft(dd, 10);
618         
619         aa = rotateOverLeft(aa + operationG(bb,cc,dd) + this.wordBuffer.getAt( 0) + 0x5a827999, 12) + ee;
620         cc = rotateOverLeft(cc, 10);
621         
622         ee = rotateOverLeft(ee + operationG(aa,bb,cc) + this.wordBuffer.getAt( 9) + 0x5a827999, 15) + dd;
623         bb = rotateOverLeft(bb, 10);
624         
625         dd = rotateOverLeft(dd + operationG(ee,aa,bb) + this.wordBuffer.getAt( 5) + 0x5a827999,  9) + cc;
626         aa = rotateOverLeft(aa, 10);
627         
628         cc = rotateOverLeft(cc + operationG(dd,ee,aa) + this.wordBuffer.getAt( 2) + 0x5a827999, 11) + bb;
629         ee = rotateOverLeft(ee, 10);
630         
631         bb = rotateOverLeft(bb + operationG(cc,dd,ee) + this.wordBuffer.getAt(14) + 0x5a827999,  7) + aa;
632         dd = rotateOverLeft(dd, 10);
633         
634         aa = rotateOverLeft(aa + operationG(bb,cc,dd) + this.wordBuffer.getAt(11) + 0x5a827999, 13) + ee;
635         cc = rotateOverLeft(cc, 10);
636         
637         ee = rotateOverLeft(ee + operationG(aa,bb,cc) + this.wordBuffer.getAt( 8) + 0x5a827999, 12) + dd;
638         bb = rotateOverLeft(bb, 10);
639         
640         
641         /*
642          * Left Side Processing
643          * Round 3, Steps 32-37
644          *
645          */
646         dd = rotateOverLeft(dd + operationH(ee,aa,bb) + this.wordBuffer.getAt( 3) + 0x6ed9eba1, 11) + cc;
647         aa = rotateOverLeft(aa, 10);
648         
649         cc = rotateOverLeft(cc + operationH(dd,ee,aa) + this.wordBuffer.getAt(10) + 0x6ed9eba1, 13) + bb;
650         ee = rotateOverLeft(ee, 10);
651         
652         bb = rotateOverLeft(bb + operationH(cc,dd,ee) + this.wordBuffer.getAt(14) + 0x6ed9eba1,  6) + aa;
653         dd = rotateOverLeft(dd, 10);
654         
655         aa = rotateOverLeft(aa + operationH(bb,cc,dd) + this.wordBuffer.getAt( 4) + 0x6ed9eba1,  7) + ee;
656         cc = rotateOverLeft(cc, 10);
657         
658         ee = rotateOverLeft(ee + operationH(aa,bb,cc) + this.wordBuffer.getAt( 9) + 0x6ed9eba1, 14) + dd;
659         bb = rotateOverLeft(bb, 10);
660         
661         dd = rotateOverLeft(dd + operationH(ee,aa,bb) + this.wordBuffer.getAt(15) + 0x6ed9eba1,  9) + cc;
662         aa = rotateOverLeft(aa, 10);
663         
664         cc = rotateOverLeft(cc + operationH(dd,ee,aa) + this.wordBuffer.getAt( 8) + 0x6ed9eba1, 13) + bb;
665         ee = rotateOverLeft(ee, 10);
666         
667         bb = rotateOverLeft(bb + operationH(cc,dd,ee) + this.wordBuffer.getAt( 1) + 0x6ed9eba1, 15) + aa;
668         dd = rotateOverLeft(dd, 10);
669         
670         aa = rotateOverLeft(aa + operationH(bb,cc,dd) + this.wordBuffer.getAt( 2) + 0x6ed9eba1, 14) + ee;
671         cc = rotateOverLeft(cc, 10);
672         
673         ee = rotateOverLeft(ee + operationH(aa,bb,cc) + this.wordBuffer.getAt( 7) + 0x6ed9eba1,  8) + dd;
674         bb = rotateOverLeft(bb, 10);
675         
676         dd = rotateOverLeft(dd + operationH(ee,aa,bb) + this.wordBuffer.getAt( 0) + 0x6ed9eba1, 13) + cc;
677         aa = rotateOverLeft(aa, 10);
678         
679         cc = rotateOverLeft(cc + operationH(dd,ee,aa) + this.wordBuffer.getAt( 6) + 0x6ed9eba1,  6) + bb;
680         ee = rotateOverLeft(ee, 10);
681         
682         bb = rotateOverLeft(bb + operationH(cc,dd,ee) + this.wordBuffer.getAt(13) + 0x6ed9eba1,  5) + aa;
683         dd = rotateOverLeft(dd, 10);
684         
685         aa = rotateOverLeft(aa + operationH(bb,cc,dd) + this.wordBuffer.getAt(11) + 0x6ed9eba1, 12) + ee;
686         cc = rotateOverLeft(cc, 10);
687         
688         ee = rotateOverLeft(ee + operationH(aa,bb,cc) + this.wordBuffer.getAt( 5) + 0x6ed9eba1,  7) + dd;
689         bb = rotateOverLeft(bb, 10);
690         
691         dd = rotateOverLeft(dd + operationH(ee,aa,bb) + this.wordBuffer.getAt(12) + 0x6ed9eba1,  5) + cc;
692         aa = rotateOverLeft(aa, 10);
693         
694         
695         /*
696          * Left Side Processing
697          * Rounds 4, Step 48-67
698          *
699          */
700         cc = rotateOverLeft(cc + operationI(dd,ee,aa) + this.wordBuffer.getAt( 1) + 0x8f1bbcdc, 11) + bb;
701         ee = rotateOverLeft(ee, 10);
702         
703         bb = rotateOverLeft(bb + operationI(cc,dd,ee) + this.wordBuffer.getAt( 9) + 0x8f1bbcdc, 12) + aa;
704         dd = rotateOverLeft(dd, 10);
705         
706         aa = rotateOverLeft(aa + operationI(bb,cc,dd) + this.wordBuffer.getAt(11) + 0x8f1bbcdc, 14) + ee;
707         cc = rotateOverLeft(cc, 10);
708         
709         ee = rotateOverLeft(ee + operationI(aa,bb,cc) + this.wordBuffer.getAt(10) + 0x8f1bbcdc, 15) + dd;
710         bb = rotateOverLeft(bb, 10);
711         
712         dd = rotateOverLeft(dd + operationI(ee,aa,bb) + this.wordBuffer.getAt( 0) + 0x8f1bbcdc, 14) + cc;
713         aa = rotateOverLeft(aa, 10);
714         
715         cc = rotateOverLeft(cc + operationI(dd,ee,aa) + this.wordBuffer.getAt( 8) + 0x8f1bbcdc, 15) + bb;
716         ee = rotateOverLeft(ee, 10);
717         
718         bb = rotateOverLeft(bb + operationI(cc,dd,ee) + this.wordBuffer.getAt(12) + 0x8f1bbcdc,  9) + aa;
719         dd = rotateOverLeft(dd, 10);
720         
721         aa = rotateOverLeft(aa + operationI(bb,cc,dd) + this.wordBuffer.getAt( 4) + 0x8f1bbcdc,  8) + ee;
722         cc = rotateOverLeft(cc, 10);
723         
724         ee = rotateOverLeft(ee + operationI(aa,bb,cc) + this.wordBuffer.getAt(13) + 0x8f1bbcdc,  9) + dd;
725         bb = rotateOverLeft(bb, 10);
726         
727         dd = rotateOverLeft(dd + operationI(ee,aa,bb) + this.wordBuffer.getAt( 3) + 0x8f1bbcdc, 14) + cc;
728         aa = rotateOverLeft(aa, 10);
729         
730         cc = rotateOverLeft(cc + operationI(dd,ee,aa) + this.wordBuffer.getAt( 7) + 0x8f1bbcdc,  5) + bb;
731         ee = rotateOverLeft(ee, 10);
732         
733         bb = rotateOverLeft(bb + operationI(cc,dd,ee) + this.wordBuffer.getAt(15) + 0x8f1bbcdc,  6) + aa;
734         dd = rotateOverLeft(dd, 10);
735         
736         aa = rotateOverLeft(aa + operationI(bb,cc,dd) + this.wordBuffer.getAt(14) + 0x8f1bbcdc,  8) + ee;
737         cc = rotateOverLeft(cc, 10);
738         
739         ee = rotateOverLeft(ee + operationI(aa,bb,cc) + this.wordBuffer.getAt( 5) + 0x8f1bbcdc,  6) + dd;
740         bb = rotateOverLeft(bb, 10);
741         
742         dd = rotateOverLeft(dd + operationI(ee,aa,bb) + this.wordBuffer.getAt( 6) + 0x8f1bbcdc,  5) + cc;
743         aa = rotateOverLeft(aa, 10);
744         
745         cc = rotateOverLeft(cc + operationI(dd,ee,aa) + this.wordBuffer.getAt( 2) + 0x8f1bbcdc, 12) + bb;
746         ee = rotateOverLeft(ee, 10);
747         
748         
749         /*
750          * Left Side Processing
751          * Rounds 5, Step 64-79
752          *
753          */
754         bb = rotateOverLeft(bb + operationJ(cc,dd,ee) + this.wordBuffer.getAt( 4) + 0xa953fd4e,  9) + aa;
755         dd = rotateOverLeft(dd, 10);
756         
757         aa = rotateOverLeft(aa + operationJ(bb,cc,dd) + this.wordBuffer.getAt( 0) + 0xa953fd4e, 15) + ee;
758         cc = rotateOverLeft(cc, 10);
759         
760         ee = rotateOverLeft(ee + operationJ(aa,bb,cc) + this.wordBuffer.getAt( 5) + 0xa953fd4e,  5) + dd;
761         bb = rotateOverLeft(bb, 10);
762         
763         dd = rotateOverLeft(dd + operationJ(ee,aa,bb) + this.wordBuffer.getAt( 9) + 0xa953fd4e, 11) + cc;
764         aa = rotateOverLeft(aa, 10);
765         
766         cc = rotateOverLeft(cc + operationJ(dd,ee,aa) + this.wordBuffer.getAt( 7) + 0xa953fd4e,  6) + bb;
767         ee = rotateOverLeft(ee, 10);
768         
769         bb = rotateOverLeft(bb + operationJ(cc,dd,ee) + this.wordBuffer.getAt(12) + 0xa953fd4e,  8) + aa;
770         dd = rotateOverLeft(dd, 10);
771         
772         aa = rotateOverLeft(aa + operationJ(bb,cc,dd) + this.wordBuffer.getAt( 2) + 0xa953fd4e, 13) + ee; 
773         cc = rotateOverLeft(cc, 10);
774         
775         ee = rotateOverLeft(ee + operationJ(aa,bb,cc) + this.wordBuffer.getAt(10) + 0xa953fd4e, 12) + dd;
776         bb = rotateOverLeft(bb, 10);
777         
778         dd = rotateOverLeft(dd + operationJ(ee,aa,bb) + this.wordBuffer.getAt(14) + 0xa953fd4e,  5) + cc; 
779         aa = rotateOverLeft(aa, 10);
780         
781         cc = rotateOverLeft(cc + operationJ(dd,ee,aa) + this.wordBuffer.getAt( 1) + 0xa953fd4e, 12) + bb;
782         ee = rotateOverLeft(ee, 10);
783         
784         bb = rotateOverLeft(bb + operationJ(cc,dd,ee) + this.wordBuffer.getAt( 3) + 0xa953fd4e, 13) + aa; 
785         dd = rotateOverLeft(dd, 10);
786         
787         aa = rotateOverLeft(aa + operationJ(bb,cc,dd) + this.wordBuffer.getAt( 8) + 0xa953fd4e, 14) + ee; 
788         cc = rotateOverLeft(cc, 10);
789         
790         ee = rotateOverLeft(ee + operationJ(aa,bb,cc) + this.wordBuffer.getAt(11) + 0xa953fd4e, 11) + dd; 
791         bb = rotateOverLeft(bb, 10);
792         
793         dd = rotateOverLeft(dd + operationJ(ee,aa,bb) + this.wordBuffer.getAt( 6) + 0xa953fd4e,  8) + cc;
794         aa = rotateOverLeft(aa, 10);
795         
796         cc = rotateOverLeft(cc + operationJ(dd,ee,aa) + this.wordBuffer.getAt(15) + 0xa953fd4e,  5) + bb;
797         ee = rotateOverLeft(ee, 10);
798         
799         bb = rotateOverLeft(bb + operationJ(cc,dd,ee) + this.wordBuffer.getAt(13) + 0xa953fd4e,  6) + aa; 
800         dd = rotateOverLeft(dd, 10);
801         
802         
803         
804         /*
805          * Right Side Processing
806          * Round 1, Steps 0-15
807          *
808          */
809         aaa = rotateOverLeft(aaa + operationJ(bbb,ccc,ddd) + this.wordBuffer.getAt( 5) + 0x50a28be6,  8) + eee;
810         ccc = rotateOverLeft(ccc, 10);
811         
812         eee = rotateOverLeft(eee + operationJ(aaa,bbb,ccc) + this.wordBuffer.getAt(14) + 0x50a28be6,  9) + ddd;
813         bbb = rotateOverLeft(bbb, 10);
814         
815         ddd = rotateOverLeft(ddd + operationJ(eee,aaa,bbb) + this.wordBuffer.getAt( 7) + 0x50a28be6,  9) + ccc;
816         aaa = rotateOverLeft(aaa, 10);
817         
818         ccc = rotateOverLeft(ccc + operationJ(ddd,eee,aaa) + this.wordBuffer.getAt( 0) + 0x50a28be6, 11) + bbb; 
819         eee = rotateOverLeft(eee, 10);
820         
821         bbb = rotateOverLeft(bbb + operationJ(ccc,ddd,eee) + this.wordBuffer.getAt( 9) + 0x50a28be6, 13) + aaa;
822         ddd = rotateOverLeft(ddd, 10);
823         
824         aaa = rotateOverLeft(aaa + operationJ(bbb,ccc,ddd) + this.wordBuffer.getAt( 2) + 0x50a28be6, 15) + eee; 
825         ccc = rotateOverLeft(ccc, 10);
826         
827         eee = rotateOverLeft(eee + operationJ(aaa,bbb,ccc) + this.wordBuffer.getAt(11) + 0x50a28be6, 15) + ddd;
828         bbb = rotateOverLeft(bbb, 10);
829         
830         ddd = rotateOverLeft(ddd + operationJ(eee,aaa,bbb) + this.wordBuffer.getAt( 4) + 0x50a28be6,  5) + ccc;
831         aaa = rotateOverLeft(aaa, 10);
832         
833         ccc = rotateOverLeft(ccc + operationJ(ddd,eee,aaa) + this.wordBuffer.getAt(13) + 0x50a28be6,  7) + bbb; 
834         eee = rotateOverLeft(eee, 10);
835         
836         bbb = rotateOverLeft(bbb + operationJ(ccc,ddd,eee) + this.wordBuffer.getAt( 6) + 0x50a28be6,  7) + aaa;
837         ddd = rotateOverLeft(ddd, 10);
838         
839         aaa = rotateOverLeft(aaa + operationJ(bbb,ccc,ddd) + this.wordBuffer.getAt(15) + 0x50a28be6,  8) + eee; 
840         ccc = rotateOverLeft(ccc, 10);
841         
842         eee = rotateOverLeft(eee + operationJ(aaa,bbb,ccc) + this.wordBuffer.getAt( 8) + 0x50a28be6, 11) + ddd;
843         bbb = rotateOverLeft(bbb, 10);
844         
845         ddd = rotateOverLeft(ddd + operationJ(eee,aaa,bbb) + this.wordBuffer.getAt( 1) + 0x50a28be6, 14) + ccc;
846         aaa = rotateOverLeft(aaa, 10);
847         
848         ccc = rotateOverLeft(ccc + operationJ(ddd,eee,aaa) + this.wordBuffer.getAt(10) + 0x50a28be6, 14) + bbb;
849         eee = rotateOverLeft(eee, 10);
850         
851         bbb = rotateOverLeft(bbb + operationJ(ccc,ddd,eee) + this.wordBuffer.getAt( 3) + 0x50a28be6, 12) + aaa;
852         ddd = rotateOverLeft(ddd, 10);
853         
854         aaa = rotateOverLeft(aaa + operationJ(bbb,ccc,ddd) + this.wordBuffer.getAt(12) + 0x50a28be6,  6) + eee;
855         ccc = rotateOverLeft(ccc, 10);
856         
857         
858         /*
859          * Left Side Processing
860          * Round 2, Steps 16-31
861          *
862          */
863         eee = rotateOverLeft(eee + operationI(aaa,bbb,ccc) + this.wordBuffer.getAt( 6) + 0x5c4dd124,  9) + ddd;
864         bbb = rotateOverLeft(bbb, 10);
865         
866         ddd = rotateOverLeft(ddd + operationI(eee,aaa,bbb) + this.wordBuffer.getAt(11) + 0x5c4dd124, 13) + ccc;
867         aaa = rotateOverLeft(aaa, 10);
868         
869         ccc = rotateOverLeft(ccc + operationI(ddd,eee,aaa) + this.wordBuffer.getAt( 3) + 0x5c4dd124, 15) + bbb;
870         eee = rotateOverLeft(eee, 10);
871         
872         bbb = rotateOverLeft(bbb + operationI(ccc,ddd,eee) + this.wordBuffer.getAt( 7) + 0x5c4dd124,  7) + aaa; 
873         ddd = rotateOverLeft(ddd, 10);
874         
875         aaa = rotateOverLeft(aaa + operationI(bbb,ccc,ddd) + this.wordBuffer.getAt( 0) + 0x5c4dd124, 12) + eee;
876         ccc = rotateOverLeft(ccc, 10);
877         
878         eee = rotateOverLeft(eee + operationI(aaa,bbb,ccc) + this.wordBuffer.getAt(13) + 0x5c4dd124,  8) + ddd;
879         bbb = rotateOverLeft(bbb, 10);
880         
881         ddd = rotateOverLeft(ddd + operationI(eee,aaa,bbb) + this.wordBuffer.getAt( 5) + 0x5c4dd124,  9) + ccc; 
882         aaa = rotateOverLeft(aaa, 10);
883         
884         ccc = rotateOverLeft(ccc + operationI(ddd,eee,aaa) + this.wordBuffer.getAt(10) + 0x5c4dd124, 11) + bbb; 
885         eee = rotateOverLeft(eee, 10);
886         
887         bbb = rotateOverLeft(bbb + operationI(ccc,ddd,eee) + this.wordBuffer.getAt(14) + 0x5c4dd124,  7) + aaa;
888         ddd = rotateOverLeft(ddd, 10);
889         
890         aaa = rotateOverLeft(aaa + operationI(bbb,ccc,ddd) + this.wordBuffer.getAt(15) + 0x5c4dd124,  7) + eee;
891         ccc = rotateOverLeft(ccc, 10);
892         
893         eee = rotateOverLeft(eee + operationI(aaa,bbb,ccc) + this.wordBuffer.getAt( 8) + 0x5c4dd124, 12) + ddd;
894         bbb = rotateOverLeft(bbb, 10);
895         
896         ddd = rotateOverLeft(ddd + operationI(eee,aaa,bbb) + this.wordBuffer.getAt(12) + 0x5c4dd124,  7) + ccc;
897         aaa = rotateOverLeft(aaa, 10);
898         
899         ccc = rotateOverLeft(ccc + operationI(ddd,eee,aaa) + this.wordBuffer.getAt( 4) + 0x5c4dd124,  6) + bbb; 
900         eee = rotateOverLeft(eee, 10);
901         
902         bbb = rotateOverLeft(bbb + operationI(ccc,ddd,eee) + this.wordBuffer.getAt( 9) + 0x5c4dd124, 15) + aaa; 
903         ddd = rotateOverLeft(ddd, 10);
904         
905         aaa = rotateOverLeft(aaa + operationI(bbb,ccc,ddd) + this.wordBuffer.getAt( 1) + 0x5c4dd124, 13) + eee;
906         ccc = rotateOverLeft(ccc, 10);
907         
908         eee = rotateOverLeft(eee + operationI(aaa,bbb,ccc) + this.wordBuffer.getAt( 2) + 0x5c4dd124, 11) + ddd;
909         bbb = rotateOverLeft(bbb, 10);
910         
911         
912         /*
913          * Left Side Processing
914          * Round 3, Steps 32-47
915          *
916          */
917         ddd = rotateOverLeft(ddd + operationH(eee,aaa,bbb) + this.wordBuffer.getAt(15) + 0x6d703ef3,  9) + ccc; 
918         aaa = rotateOverLeft(aaa, 10);
919         
920         ccc = rotateOverLeft(ccc + operationH(ddd,eee,aaa) + this.wordBuffer.getAt( 5) + 0x6d703ef3,  7) + bbb; 
921         eee = rotateOverLeft(eee, 10);
922         
923         bbb = rotateOverLeft(bbb + operationH(ccc,ddd,eee) + this.wordBuffer.getAt( 1) + 0x6d703ef3, 15) + aaa;
924         ddd = rotateOverLeft(ddd, 10);
925         
926         aaa = rotateOverLeft(aaa + operationH(bbb,ccc,ddd) + this.wordBuffer.getAt( 3) + 0x6d703ef3, 11) + eee; 
927         ccc = rotateOverLeft(ccc, 10);
928         
929         eee = rotateOverLeft(eee + operationH(aaa,bbb,ccc) + this.wordBuffer.getAt( 7) + 0x6d703ef3,  8) + ddd;
930         bbb = rotateOverLeft(bbb, 10);
931         
932         ddd = rotateOverLeft(ddd + operationH(eee,aaa,bbb) + this.wordBuffer.getAt(14) + 0x6d703ef3,  6) + ccc;
933         aaa = rotateOverLeft(aaa, 10);
934         
935         ccc = rotateOverLeft(ccc + operationH(ddd,eee,aaa) + this.wordBuffer.getAt( 6) + 0x6d703ef3,  6) + bbb; 
936         eee = rotateOverLeft(eee, 10);
937         
938         bbb = rotateOverLeft(bbb + operationH(ccc,ddd,eee) + this.wordBuffer.getAt( 9) + 0x6d703ef3, 14) + aaa;
939         ddd = rotateOverLeft(ddd, 10);
940         
941         aaa = rotateOverLeft(aaa + operationH(bbb,ccc,ddd) + this.wordBuffer.getAt(11) + 0x6d703ef3, 12) + eee;
942         ccc = rotateOverLeft(ccc, 10);
943         
944         eee = rotateOverLeft(eee + operationH(aaa,bbb,ccc) + this.wordBuffer.getAt( 8) + 0x6d703ef3, 13) + ddd;
945         bbb = rotateOverLeft(bbb, 10);
946         
947         ddd = rotateOverLeft(ddd + operationH(eee,aaa,bbb) + this.wordBuffer.getAt(12) + 0x6d703ef3,  5) + ccc; 
948         aaa = rotateOverLeft(aaa, 10);
949         
950         ccc = rotateOverLeft(ccc + operationH(ddd,eee,aaa) + this.wordBuffer.getAt( 2) + 0x6d703ef3, 14) + bbb; 
951         eee = rotateOverLeft(eee, 10);
952         
953         bbb = rotateOverLeft(bbb + operationH(ccc,ddd,eee) + this.wordBuffer.getAt(10) + 0x6d703ef3, 13) + aaa;
954         ddd = rotateOverLeft(ddd, 10);
955         
956         aaa = rotateOverLeft(aaa + operationH(bbb,ccc,ddd) + this.wordBuffer.getAt( 0) + 0x6d703ef3, 13) + eee;
957         ccc = rotateOverLeft(ccc, 10);
958         
959         eee = rotateOverLeft(eee + operationH(aaa,bbb,ccc) + this.wordBuffer.getAt( 4) + 0x6d703ef3,  7) + ddd;
960         bbb = rotateOverLeft(bbb, 10);
961         
962         ddd = rotateOverLeft(ddd + operationH(eee,aaa,bbb) + this.wordBuffer.getAt(13) + 0x6d703ef3,  5) + ccc;
963         aaa = rotateOverLeft(aaa, 10);
964         
965         
966         /*
967          * Left Side Processing
968          * Round 4, Steps 48-63
969          *
970          */
971         ccc = rotateOverLeft(ccc + operationG(ddd,eee,aaa) + this.wordBuffer.getAt( 8) + 0x7a6d76e9, 15) + bbb; 
972         eee = rotateOverLeft(eee, 10);
973         
974         bbb = rotateOverLeft(bbb + operationG(ccc,ddd,eee) + this.wordBuffer.getAt( 6) + 0x7a6d76e9,  5) + aaa; 
975         ddd = rotateOverLeft(ddd, 10);
976         
977         aaa = rotateOverLeft(aaa + operationG(bbb,ccc,ddd) + this.wordBuffer.getAt( 4) + 0x7a6d76e9,  8) + eee;
978         ccc = rotateOverLeft(ccc, 10);
979         
980         eee = rotateOverLeft(eee + operationG(aaa,bbb,ccc) + this.wordBuffer.getAt( 1) + 0x7a6d76e9, 11) + ddd;
981         bbb = rotateOverLeft(bbb, 10);
982         
983         ddd = rotateOverLeft(ddd + operationG(eee,aaa,bbb) + this.wordBuffer.getAt( 3) + 0x7a6d76e9, 14) + ccc;
984         aaa = rotateOverLeft(aaa, 10);
985         
986         ccc = rotateOverLeft(ccc + operationG(ddd,eee,aaa) + this.wordBuffer.getAt(11) + 0x7a6d76e9, 14) + bbb;
987         eee = rotateOverLeft(eee, 10);
988         
989         bbb = rotateOverLeft(bbb + operationG(ccc,ddd,eee) + this.wordBuffer.getAt(15) + 0x7a6d76e9,  6) + aaa; 
990         ddd = rotateOverLeft(ddd, 10);
991         
992         aaa = rotateOverLeft(aaa + operationG(bbb,ccc,ddd) + this.wordBuffer.getAt( 0) + 0x7a6d76e9, 14) + eee;
993         ccc = rotateOverLeft(ccc, 10);
994         
995         eee = rotateOverLeft(eee + operationG(aaa,bbb,ccc) + this.wordBuffer.getAt( 5) + 0x7a6d76e9,  6) + ddd;
996         bbb = rotateOverLeft(bbb, 10);
997         
998         ddd = rotateOverLeft(ddd + operationG(eee,aaa,bbb) + this.wordBuffer.getAt(12) + 0x7a6d76e9,  9) + ccc;
999         aaa = rotateOverLeft(aaa, 10);
1000        
1001        ccc = rotateOverLeft(ccc + operationG(ddd,eee,aaa) + this.wordBuffer.getAt( 2) + 0x7a6d76e9, 12) + bbb;
1002        eee = rotateOverLeft(eee, 10);
1003        
1004        bbb = rotateOverLeft(bbb + operationG(ccc,ddd,eee) + this.wordBuffer.getAt(13) + 0x7a6d76e9,  9) + aaa;
1005        ddd = rotateOverLeft(ddd, 10);
1006        
1007        aaa = rotateOverLeft(aaa + operationG(bbb,ccc,ddd) + this.wordBuffer.getAt( 9) + 0x7a6d76e9, 12) + eee; 
1008        ccc = rotateOverLeft(ccc, 10);
1009        
1010        eee = rotateOverLeft(eee + operationG(aaa,bbb,ccc) + this.wordBuffer.getAt( 7) + 0x7a6d76e9,  5) + ddd;
1011        bbb = rotateOverLeft(bbb, 10);
1012        
1013        ddd = rotateOverLeft(ddd + operationG(eee,aaa,bbb) + this.wordBuffer.getAt(10) + 0x7a6d76e9, 15) + ccc;
1014        aaa = rotateOverLeft(aaa, 10);
1015        
1016        ccc = rotateOverLeft(ccc + operationG(ddd,eee,aaa) + this.wordBuffer.getAt(14) + 0x7a6d76e9,  8) + bbb; 
1017        eee = rotateOverLeft(eee, 10);
1018        
1019        
1020        /*
1021         * Left Side Processing
1022         * Round 5, Steps 64-79
1023         *
1024         */
1025        bbb = rotateOverLeft(bbb + operationF(ccc,ddd,eee) + this.wordBuffer.getAt(12),  8) + aaa;
1026        ddd = rotateOverLeft(ddd, 10);
1027        
1028        aaa = rotateOverLeft(aaa + operationF(bbb,ccc,ddd) + this.wordBuffer.getAt(15),  5) + eee;
1029        ccc = rotateOverLeft(ccc, 10);
1030        
1031        eee = rotateOverLeft(eee + operationF(aaa,bbb,ccc) + this.wordBuffer.getAt(10), 12) + ddd; 
1032        bbb = rotateOverLeft(bbb, 10);
1033        
1034        ddd = rotateOverLeft(ddd + operationF(eee,aaa,bbb) + this.wordBuffer.getAt( 4),  9) + ccc; 
1035        aaa = rotateOverLeft(aaa, 10);
1036        
1037        ccc = rotateOverLeft(ccc + operationF(ddd,eee,aaa) + this.wordBuffer.getAt( 1), 12) + bbb;
1038        eee = rotateOverLeft(eee, 10);
1039        
1040        bbb = rotateOverLeft(bbb + operationF(ccc,ddd,eee) + this.wordBuffer.getAt( 5),  5) + aaa;
1041        ddd = rotateOverLeft(ddd, 10);
1042        
1043        aaa = rotateOverLeft(aaa + operationF(bbb,ccc,ddd) + this.wordBuffer.getAt( 8), 14) + eee;
1044        ccc = rotateOverLeft(ccc, 10);
1045        
1046        eee = rotateOverLeft(eee + operationF(aaa,bbb,ccc) + this.wordBuffer.getAt( 7),  6) + ddd;
1047        bbb = rotateOverLeft(bbb, 10);
1048        
1049        ddd = rotateOverLeft(ddd + operationF(eee,aaa,bbb) + this.wordBuffer.getAt( 6),  8) + ccc; 
1050        aaa = rotateOverLeft(aaa, 10);
1051        
1052        ccc = rotateOverLeft(ccc + operationF(ddd,eee,aaa) + this.wordBuffer.getAt( 2), 13) + bbb; 
1053        eee = rotateOverLeft(eee, 10);
1054        
1055        bbb = rotateOverLeft(bbb + operationF(ccc,ddd,eee) + this.wordBuffer.getAt(13),  6) + aaa;
1056        ddd = rotateOverLeft(ddd, 10);
1057        
1058        aaa = rotateOverLeft(aaa + operationF(bbb,ccc,ddd) + this.wordBuffer.getAt(14),  5) + eee;
1059        ccc = rotateOverLeft(ccc, 10);
1060        
1061        eee = rotateOverLeft(eee + operationF(aaa,bbb,ccc) + this.wordBuffer.getAt( 0), 15) + ddd; 
1062        bbb = rotateOverLeft(bbb, 10);
1063        
1064        ddd = rotateOverLeft(ddd + operationF(eee,aaa,bbb) + this.wordBuffer.getAt( 3), 13) + ccc; 
1065        aaa = rotateOverLeft(aaa, 10);
1066        
1067        ccc = rotateOverLeft(ccc + operationF(ddd,eee,aaa) + this.wordBuffer.getAt( 9), 11) + bbb;
1068        eee = rotateOverLeft(eee, 10);
1069        
1070        bbb = rotateOverLeft(bbb + operationF(ccc,ddd,eee) + this.wordBuffer.getAt(11), 11) + aaa;
1071        ddd = rotateOverLeft(ddd, 10);
1072        
1073        
1074        /* Put the result from the left and right side of the RIPMD-160 Algo
1075         * together.
1076         *
1077         * The compressed results from the wordBuffer, now are added to
1078         * results or IVs in the messageDigest 32 bit register. It can happend
1079         * that the five internal 32 bit registers (int) overflow, but this is 
1080         * part of the Algo and is no problem.
1081         */
1082        ddd += cc + this.messageDigest.getAt(1);    // final result for MDbuf[0]
1083        this.messageDigest.setAt(1, this.messageDigest.getAt(2) + dd + eee);
1084        this.messageDigest.setAt(2, this.messageDigest.getAt(3) + ee + aaa);
1085        this.messageDigest.setAt(3, this.messageDigest.getAt(4) + aa + bbb);
1086        this.messageDigest.setAt(4, this.messageDigest.getAt(0) + bb + ccc);
1087        this.messageDigest.setAt(0, ddd);
1088        
1089        
1090        /*
1091         * At these point we reset the this.wordBuffer
1092         */
1093        this.wordBuffer.reset();
1094    }
1095}
1096