1   /* $RCSfile: RIPEMD160MessageDigestBuffer.java,v $
2    * $Revision: 1.11 $
3    * $Date: 2002/01/17 19:24:55 $
4    * $Author: uwe $
5    * $State: Exp $
6    *
7    * Created on July 13, 2001, 5:57 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.ByteUtil;
37  
38  /**
39   * RIPEMD160MessageDigestBuffer Class.
40   *
41   * @author  <a href=mailto:uwe@cscc.de>Uwe G&uuml;nther</a>
42   * @version $Revision: 1.11 $
43   */
44  class RIPEMD160MessageDigestBuffer implements Cloneable {
45  
46      /** 
47       * Initialize vector for the RIPEMD160 algorithm. 
48       * The representation in the code below is in big endian notation.
49       * RIPEMD-160 defines the IV in little endian as follows:
50       * IV = {0x01234567, 0x89abcdef 0xfedcba98 0x76543210 0xf0e1d2c3}
51       * But we need the big endian notaion.
52       */
53      private static final int[] INITIALIZE_VECTOR = {
54          0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0
55      };   
56      
57      /**
58       * The length of the message digest result vector 
59       * <CODE>messageDigest</CODE> in words.
60       */
61      private static final int BUFFER_LENGTH = 5;
62      
63      /**
64       * Internal messageDigest repesentation array for the 
65       * five MD words == 160 bit or 20 byte.
66       */    
67      private int[] buffer = new int[BUFFER_LENGTH];
68      
69      /** Creates new RIPEMD160MessageDigestBuffer. */
70      public RIPEMD160MessageDigestBuffer() {        
71          System.arraycopy(INITIALIZE_VECTOR, 0, this.buffer, 0, 5);
72      }
73      
74      /** 
75       * Creates and returns a deep copy of this object.
76       * @return a clone of this instance.
77       * @see java.lang.Cloneable
78       * @exception CloneNotSupportedException if the object's class does not
79       *             support the <code>Cloneable</code> interface. Subclasses
80       *             that override the <code>clone</code> method can also
81       *             throw this exception to indicate that an instance cannot
82       *             be cloned.
83       */
84      public Object clone() throws CloneNotSupportedException {
85          RIPEMD160MessageDigestBuffer result = 
86                  (RIPEMD160MessageDigestBuffer) super.clone();
87          result.buffer = (int[]) this.buffer.clone();
88          return result;
89      }        
90      
91      /** 
92       * Indicates whether some other object is "equal to" this one.
93       *
94       * @param   obj   the reference object with which to compare.
95       * @return  <code>true</code> if this object is the same as the obj
96       *         argument; <code>false</code> otherwise.
97       * @see     #hashCode()
98       * @see     java.util.Hashtable
99       */
100     public boolean equals(Object obj) {       
101         //Only for performance.
102         if (this == obj) {
103             return true;
104         } 
105         
106         //If obj == null then instanceof returns false, see JLS 15.20.2
107         if (!(obj instanceof RIPEMD160MessageDigestBuffer)) {
108             return false;
109         }
110          
111         RIPEMD160MessageDigestBuffer other = (RIPEMD160MessageDigestBuffer) obj;
112         return Arrays.equals(this.buffer, other.buffer);
113     }
114     
115     /** 
116      * Returns a hash code value for the object. This method is
117      * supported for the benefit of hashtables such as those provided by
118      * <code>java.util.Hashtable</code>.
119      *
120      * @return  a hash code value for this object.
121      * @see     #equals(java.lang.Object)
122      * @see     java.util.Hashtable
123      */
124     public int hashCode() {
125         int result = 17;
126         for (int i = 0; i < this.buffer.length; i++) {
127             result = 37*result + this.buffer[i];
128         }
129         return result;
130     }            
131     
132     /**
133      * Returns a string representation of the object.
134      *
135      * @return  a string representation of the object.
136      */
137     public String toString() {
138         return "[buffer: " + ByteUtil.toHex(toByteBuffer()) + "]";
139     }
140     
141     /** 
142      * We do init the buffer (the five message digest value registers) with
143      * the initial values descriped on the RIPEMD-Homepage.
144      */    
145     public void init() {
146         System.arraycopy(INITIALIZE_VECTOR, 0, this.buffer, 0, 5);
147     }
148     
149     /**
150      * Return the digest as byte[5] array.
151      *
152      * <p>The message digest produced as output is:
153      *
154      * <p>MDbuf[0], MDbuf[1], Mdbuf[2], MDbuf[3], MDbuf[4]. That is we begin
155      * with the least significant byte of MDbuf[0] and and with the most
156      * significant byte of MDbuf[4];
157      * <p>
158      * Convert the five MDbuf registers back to
159      * byte returnValue[DIGEST_LENGTH] or byte returnValue[20] in
160      * little endian byte order.
161      * <pre>
162      *  returnValue[ 0] = (byte)(buffer[0] >>> 0);  //least significant byte
163      *  returnValue[ 1] = (byte)(buffer[0] >>> 8);
164      *  returnValue[ 2] = (byte)(buffer[0] >>> 16);
165      *  returnValue[ 3] = (byte)(buffer[0] >>> 24); // most significant byte
166      *  returnValue[ 4] = (byte)(buffer[1] >>> 0);  //least significant byte
167      *  returnValue[ 5] = (byte)(buffer[1] >>> 8);
168      *                      .
169      *                      .
170      *                      .
171      *  returnValue[19] = (byte)(buffer[4] >>> 24); // most significant byte
172      * </pre>
173      *
174      * @return the message digest representation in byte notation.
175      * This array is used to exchange the digest value.
176      */
177     public byte[] toByteBuffer() {
178         byte[] returnValue = new byte[4*BUFFER_LENGTH];
179         for(int i = 0; i < 5; i++) {
180             for(int j = 0; j < 4; j++) {
181                 returnValue[j + i * 4] = (byte) (this.buffer[i] >>> (j*8));
182             }
183         }
184 
185         return returnValue;        
186     }
187     
188     /** 
189      * Used to set the value in the internal buffer at pos,
190      * if pos 5 or greater than 5 IndexOutOfBoundsException
191      * will be thrown.
192      *
193      * @param pos index to acces the buffer, must be less than 5.
194      * @param value value to be set.
195      * @throws IndexOutOfBoundsException thrown if pos 5 or greater than 5.
196      */    
197     public void setAt(int pos, int value) {
198         buffer[pos] = value;
199     }
200 
201     /** 
202      * Get the value at pos, if pos 5 or greater than 5
203      * IndexOutOfBoundsException will be thrown.
204      * @param pos index to acces the buffer, must be less than 5.
205      * @throws IndexOutOfBoundsException thrown if pos 5 or greater than 5.
206      * @return value at pos.
207      */    
208     public int getAt(int pos) {
209         return buffer[pos];
210     }
211 }
212