1   /* $RCSfile: RIPEMD160WordBuffer.java,v $
2    * $Revision: 1.10 $
3    * $Date: 2002/01/17 19:24:55 $
4    * $Author: uwe $
5    * $State: Exp $
6    *
7    * Created on July 15, 2001, 1:20 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.util.Arrays;
35  
36  import de.cscc.crypto.util.IntegerUtil;
37  
38  /** 
39   * This class is used to save a whole block (512bit) that are processed by
40   * the RIPEMD160 algorithm.
41   *
42   * @author  <a href=mailto:uwe@cscc.de>Uwe G&uuml;nther</a>
43   * @version $Revision: 1.10 $
44   */
45  class RIPEMD160WordBuffer implements Cloneable {
46      
47      /** The length of the internal <CODE>wordBuffer</CODE> in words (32 Bit). */
48      private static final int BUFFER_LENGTH =16;
49  
50      /** Holds the 512 bit message lock. */
51      private int[] buffer = new int[BUFFER_LENGTH];
52  
53      /** Counts how full is the internal <CODE>wordBuffer</CODE>. */
54      private int bufferOffset = 0;
55      
56      /** Creates new RIPEMD160WordBuffer. */
57      public RIPEMD160WordBuffer() {}
58      
59      /** 
60       * Creates and returns a deep copy of this object.
61       *
62       * @return a clone of this instance.
63       * @see java.lang.Cloneable
64       * @exception CloneNotSupportedException if the object's class does not
65       *             support the <code>Cloneable</code> interface. Subclasses
66       *             that override the <code>clone</code> method can also
67       *             throw this exception to indicate that an instance cannot
68       *             be cloned.
69       */
70      public Object clone() throws CloneNotSupportedException {
71          RIPEMD160WordBuffer result = (RIPEMD160WordBuffer) super.clone();
72          result.buffer = (int[])this.buffer.clone();
73          return result;
74      }    
75      
76      /**
77       * Indicates whether some other object is "equal to" this one.
78       *
79       * @param   obj   the reference object with which to compare.
80       * @return  <code>true</code> if this object is the same as the obj
81       *         argument; <code>false</code> otherwise.
82       * @see     #hashCode()
83       * @see     java.util.Hashtable
84       */
85      public boolean equals(Object obj) {
86          //Only for performance.
87          if (this == obj) {
88              return true;
89          } 
90          
91          //If obj == null then instanceof returns false, see JLS 15.20.2
92          if (!(obj instanceof RIPEMD160WordBuffer)) {                      
93              return false;
94          }
95  
96          RIPEMD160WordBuffer other = (RIPEMD160WordBuffer)obj;
97          
98          if (this.bufferOffset != other.bufferOffset) {
99              return false; //not equal
100         }
101         for (int i = 0; i < this.bufferOffset; i++) {
102             if (this.buffer[i] != other.buffer[i]) {
103                 return false; //not equal
104             }
105         }
106         return true; //equal
107     }
108     
109     /** 
110      * Returns a hash code value for the object. This method is
111      * supported for the benefit of hashtables such as those provided by
112      * <code>java.util.Hashtable</code>.
113      *
114      * @return  a hash code value for this object.
115      * @see     #equals(java.lang.Object)
116      * @see     java.util.Hashtable
117      */
118     public int hashCode() {
119         int result = 17;
120         for (int i = 0; i <  this.bufferOffset; i++) {
121             result = 37*result + this.buffer[i];
122         }
123         return result;
124     }            
125     
126     /**
127      * Returns a string representation of the object.
128      *
129      * @return  a string representation of the object.
130      */
131     public String toString() {
132  
133         return "[buffer: " + IntegerUtil.toHex(this.buffer) + 
134                " bufferOffset: " +  this.bufferOffset + "]";
135     }
136     
137     /**
138      * Fills the internal buffer with words. If there are more than 16 words
139      * added, you should call {@link #reset() reset()}, otherwise the
140      * ArrayIndexOutOfBoundsException will be thrown.
141      *
142      * @param in word that will be added into internal buffer.
143      * @throws ArrayIndexOutOfBoundsException if there are more than 16 words
144      * added.
145      */
146     public void set(int in) {
147         if (isFull()) {
148             throw new ArrayIndexOutOfBoundsException(bufferOffset);
149         }
150 
151         this.buffer[this.bufferOffset] = in;
152         this.bufferOffset++;        
153     }
154     
155     /**
156      * Returns the element at <code>pos</code>. Parameter <code>pos</pos> must
157      * be less than 16, the current <code>BUFFER_LENGTH</code>.
158      *
159      * @return value at pos.
160      * @param pos index to access the value from the internal buffer.
161      * @throws IndexOutOfBoundsException if pos is 16 or greater than 16.
162      */  
163     public int getAt(int pos) {
164         return buffer[pos];
165     }    
166     
167     /** 
168      * In wordBuffer is not enough space (two words) to fill the
169      * long value finalBitLength.
170      *
171      * All unused words, in this case wordBuffer[15] are filled
172      * with 0 (Zero) words due the method reset()
173      * So we do not fill these word here!
174      *
175      * BUFFER_LENGTH-2 means here 14, because the wordBufferOffset
176      * points actually to the next free word in wordBuffer.
177      * We need two free words at the end of the actually wordBuffer, to put
178      * the finalBitLength (current 64 Bit or 2 x 32 Bit) at the end of the
179      * wordBuffer.
180      *
181      * @return true if are less than two words free in the internal buffer.
182      */    
183     public boolean areLessThanTwoWordsFree() {
184         return (this.bufferOffset > RIPEMD160WordBuffer.BUFFER_LENGTH - 2);
185     }
186     
187     /** 
188      * Indicates if the internal buffer is full.
189      *
190      * @return true if the internal buffer is full.
191      */
192     public boolean isFull() {
193         return (this.bufferOffset == RIPEMD160WordBuffer.BUFFER_LENGTH);
194     }
195 
196     /**
197      * These method will reset the internal <CODE>buffer[4]</CODE> and the
198      * internal <CODE>bufferOffset</CODE> counter.
199      */    
200     public void reset() { 
201         this.bufferOffset = 0;        
202         Arrays.fill(this.buffer, 0);
203     }
204 
205     /** 
206      * We put here the finalBitLength at the end of the current wordBuffer
207      * All words less than 14 have current values or filled with 0 (Zero)
208      * by default due the method reset() called from
209      * RIPEMD160Digest.processWordBuffer().
210      *
211      * So we don't have to do the Zero filling, because it is done in the
212      * from reset().
213      *
214      * @param finalBitLength number of added message bytes * 8. This value is 
215      * used for the RIPEMD160 algorithm to do final padding.
216      */
217     public void doFinalPadding(long finalBitLength){
218         
219         this.buffer[14] = (int)(finalBitLength & 0xffffffff);
220         this.buffer[15] = (int)(finalBitLength >>> 32);   
221     }
222 }
223