OSDN Git Service

Imported GNU Classpath 0.90
[pf3gnuchains/gcc-fork.git] / libjava / classpath / gnu / java / security / hash / RipeMD160.java
1 /* RipeMD160.java -- 
2    Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
3
4 This file is a part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or (at
9 your option) any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
19 USA
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version.  */
37
38
39 package gnu.java.security.hash;
40
41 import gnu.java.security.Registry;
42 import gnu.java.security.util.Util;
43
44 /**
45  * <p>RIPEMD-160 is a 160-bit message digest.</p>
46  *
47  * <p>References:</p>
48  *
49  * <ol>
50  *    <li><a href="http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html">
51  *    RIPEMD160</a>: A Strengthened Version of RIPEMD.<br>
52  *    Hans Dobbertin, Antoon Bosselaers and Bart Preneel.</li>
53  * </ol>
54  */
55 public class RipeMD160 extends BaseHash
56 {
57
58   // Constants and variables
59   // -------------------------------------------------------------------------
60
61   private static final int BLOCK_SIZE = 64; // inner block size in bytes
62
63   private static final String DIGEST0 = "9C1185A5C5E9FC54612808977EE8F548B2258D31";
64
65   // selection of message word
66   private static final int[] R = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
67                                   13, 14, 15, 7, 4, 13, 1, 10, 6, 15, 3, 12, 0,
68                                   9, 5, 2, 14, 11, 8, 3, 10, 14, 4, 9, 15, 8,
69                                   1, 2, 7, 0, 6, 13, 11, 5, 12, 1, 9, 11, 10,
70                                   0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, 4, 0,
71                                   5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15,
72                                   13 };
73
74   private static final int[] Rp = { 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1,
75                                    10, 3, 12, 6, 11, 3, 7, 0, 13, 5, 10, 14,
76                                    15, 8, 12, 4, 9, 1, 2, 15, 5, 1, 3, 7, 14,
77                                    6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 8, 6, 4,
78                                    1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
79                                    12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0,
80                                    3, 9, 11 };
81
82   // amount for rotate left (rol)
83   private static final int[] S = { 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15,
84                                   6, 7, 9, 8, 7, 6, 8, 13, 11, 9, 7, 15, 7, 12,
85                                   15, 9, 11, 7, 13, 12, 11, 13, 6, 7, 14, 9,
86                                   13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 11, 12,
87                                   14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5,
88                                   12, 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13,
89                                   14, 11, 8, 5, 6 };
90
91   private static final int[] Sp = { 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11,
92                                    14, 14, 12, 6, 9, 13, 15, 7, 12, 8, 9, 11,
93                                    7, 7, 12, 7, 6, 15, 13, 11, 9, 7, 15, 11, 8,
94                                    6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 15,
95                                    5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5,
96                                    15, 8, 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6,
97                                    5, 15, 13, 11, 11 };
98
99   /** caches the result of the correctness test, once executed. */
100   private static Boolean valid;
101
102   /** 160-bit h0, h1, h2, h3, h4 (interim result) */
103   private int h0, h1, h2, h3, h4;
104
105   /** 512 bits work buffer = 16 x 32-bit words */
106   private int[] X = new int[16];
107
108   // Constructor(s)
109   // -------------------------------------------------------------------------
110
111   /** Trivial 0-arguments constructor. */
112   public RipeMD160()
113   {
114     super(Registry.RIPEMD160_HASH, 20, BLOCK_SIZE);
115   }
116
117   /**
118    * <p>Private constructor for cloning purposes.</p>
119    *
120    * @param md the instance to clone.
121    */
122   private RipeMD160(RipeMD160 md)
123   {
124     this();
125
126     this.h0 = md.h0;
127     this.h1 = md.h1;
128     this.h2 = md.h2;
129     this.h3 = md.h3;
130     this.h4 = md.h4;
131     this.count = md.count;
132     this.buffer = (byte[]) md.buffer.clone();
133   }
134
135   // Class methods
136   // -------------------------------------------------------------------------
137
138   // Instance methods
139   // -------------------------------------------------------------------------
140
141   // java.lang.Cloneable interface implementation ----------------------------
142
143   public Object clone()
144   {
145     return (new RipeMD160(this));
146   }
147
148   // Implementation of concrete methods in BaseHash --------------------------
149
150   protected void transform(byte[] in, int offset)
151   {
152     int A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, T, s, i;
153
154     // encode 64 bytes from input block into an array of 16 unsigned integers
155     for (i = 0; i < 16; i++)
156       {
157         X[i] = (in[offset++] & 0xFF) | (in[offset++] & 0xFF) << 8
158                | (in[offset++] & 0xFF) << 16 | in[offset++] << 24;
159       }
160
161     A = Ap = h0;
162     B = Bp = h1;
163     C = Cp = h2;
164     D = Dp = h3;
165     E = Ep = h4;
166
167     for (i = 0; i < 16; i++)
168       { // rounds 0...15
169         s = S[i];
170         T = A + (B ^ C ^ D) + X[i];
171         A = E;
172         E = D;
173         D = C << 10 | C >>> 22;
174         C = B;
175         B = (T << s | T >>> (32 - s)) + A;
176
177         s = Sp[i];
178         T = Ap + (Bp ^ (Cp | ~Dp)) + X[Rp[i]] + 0x50A28BE6;
179         Ap = Ep;
180         Ep = Dp;
181         Dp = Cp << 10 | Cp >>> 22;
182         Cp = Bp;
183         Bp = (T << s | T >>> (32 - s)) + Ap;
184       }
185
186     for (; i < 32; i++)
187       { // rounds 16...31
188         s = S[i];
189         T = A + ((B & C) | (~B & D)) + X[R[i]] + 0x5A827999;
190         A = E;
191         E = D;
192         D = C << 10 | C >>> 22;
193         C = B;
194         B = (T << s | T >>> (32 - s)) + A;
195
196         s = Sp[i];
197         T = Ap + ((Bp & Dp) | (Cp & ~Dp)) + X[Rp[i]] + 0x5C4DD124;
198         Ap = Ep;
199         Ep = Dp;
200         Dp = Cp << 10 | Cp >>> 22;
201         Cp = Bp;
202         Bp = (T << s | T >>> (32 - s)) + Ap;
203       }
204
205     for (; i < 48; i++)
206       { // rounds 32...47
207         s = S[i];
208         T = A + ((B | ~C) ^ D) + X[R[i]] + 0x6ED9EBA1;
209         A = E;
210         E = D;
211         D = C << 10 | C >>> 22;
212         C = B;
213         B = (T << s | T >>> (32 - s)) + A;
214
215         s = Sp[i];
216         T = Ap + ((Bp | ~Cp) ^ Dp) + X[Rp[i]] + 0x6D703EF3;
217         Ap = Ep;
218         Ep = Dp;
219         Dp = Cp << 10 | Cp >>> 22;
220         Cp = Bp;
221         Bp = (T << s | T >>> (32 - s)) + Ap;
222       }
223
224     for (; i < 64; i++)
225       { // rounds 48...63
226         s = S[i];
227         T = A + ((B & D) | (C & ~D)) + X[R[i]] + 0x8F1BBCDC;
228         A = E;
229         E = D;
230         D = C << 10 | C >>> 22;
231         C = B;
232         B = (T << s | T >>> (32 - s)) + A;
233
234         s = Sp[i];
235         T = Ap + ((Bp & Cp) | (~Bp & Dp)) + X[Rp[i]] + 0x7A6D76E9;
236         Ap = Ep;
237         Ep = Dp;
238         Dp = Cp << 10 | Cp >>> 22;
239         Cp = Bp;
240         Bp = (T << s | T >>> (32 - s)) + Ap;
241       }
242
243     for (; i < 80; i++)
244       { // rounds 64...79
245         s = S[i];
246         T = A + (B ^ (C | ~D)) + X[R[i]] + 0xA953FD4E;
247         A = E;
248         E = D;
249         D = C << 10 | C >>> 22;
250         C = B;
251         B = (T << s | T >>> (32 - s)) + A;
252
253         s = Sp[i];
254         T = Ap + (Bp ^ Cp ^ Dp) + X[Rp[i]];
255         Ap = Ep;
256         Ep = Dp;
257         Dp = Cp << 10 | Cp >>> 22;
258         Cp = Bp;
259         Bp = (T << s | T >>> (32 - s)) + Ap;
260       }
261
262     T = h1 + C + Dp;
263     h1 = h2 + D + Ep;
264     h2 = h3 + E + Ap;
265     h3 = h4 + A + Bp;
266     h4 = h0 + B + Cp;
267     h0 = T;
268   }
269
270   protected byte[] padBuffer()
271   {
272     int n = (int) (count % BLOCK_SIZE);
273     int padding = (n < 56) ? (56 - n) : (120 - n);
274     byte[] result = new byte[padding + 8];
275
276     // padding is always binary 1 followed by binary 0s
277     result[0] = (byte) 0x80;
278
279     // save number of bits, casting the long to an array of 8 bytes
280     long bits = count << 3;
281     result[padding++] = (byte) bits;
282     result[padding++] = (byte) (bits >>> 8);
283     result[padding++] = (byte) (bits >>> 16);
284     result[padding++] = (byte) (bits >>> 24);
285     result[padding++] = (byte) (bits >>> 32);
286     result[padding++] = (byte) (bits >>> 40);
287     result[padding++] = (byte) (bits >>> 48);
288     result[padding] = (byte) (bits >>> 56);
289
290     return result;
291   }
292
293   protected byte[] getResult()
294   {
295     byte[] result = new byte[] { (byte) h0, (byte) (h0 >>> 8),
296                                 (byte) (h0 >>> 16), (byte) (h0 >>> 24),
297                                 (byte) h1, (byte) (h1 >>> 8),
298                                 (byte) (h1 >>> 16), (byte) (h1 >>> 24),
299                                 (byte) h2, (byte) (h2 >>> 8),
300                                 (byte) (h2 >>> 16), (byte) (h2 >>> 24),
301                                 (byte) h3, (byte) (h3 >>> 8),
302                                 (byte) (h3 >>> 16), (byte) (h3 >>> 24),
303                                 (byte) h4, (byte) (h4 >>> 8),
304                                 (byte) (h4 >>> 16), (byte) (h4 >>> 24) };
305
306     return result;
307   }
308
309   protected void resetContext()
310   {
311     // magic RIPEMD160 initialisation constants
312     h0 = 0x67452301;
313     h1 = 0xEFCDAB89;
314     h2 = 0x98BADCFE;
315     h3 = 0x10325476;
316     h4 = 0xC3D2E1F0;
317   }
318
319   public boolean selfTest()
320   {
321     if (valid == null)
322       {
323         valid = Boolean.valueOf
324           (DIGEST0.equals(Util.toString(new RipeMD160().digest())));
325       }
326     return valid.booleanValue();
327   }
328 }