KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > quadcap > crypto > SHA1Digest


1 /* Copyright 2003 Quadcap Software. All rights reserved.
2  *
3  * This software is distributed under the Quadcap Free Software License.
4  * This software may be used or modified for any purpose, personal or
5  * commercial. Open Source redistributions are permitted. Commercial
6  * redistribution of larger works derived from, or works which bundle
7  * this software requires a "Commercial Redistribution License"; see
8  * http://www.quadcap.com/purchase.
9  *
10  * Redistributions qualify as "Open Source" under one of the following terms:
11  *
12  * Redistributions are made at no charge beyond the reasonable cost of
13  * materials and delivery.
14  *
15  * Redistributions are accompanied by a copy of the Source Code or by an
16  * irrevocable offer to provide a copy of the Source Code for up to three
17  * years at the cost of materials and delivery. Such redistributions
18  * must allow further use, modification, and redistribution of the Source
19  * Code under substantially the same terms as this license.
20  *
21  * Redistributions of source code must retain the copyright notices as they
22  * appear in each source code file, these license terms, and the
23  * disclaimer/limitation of liability set forth as paragraph 6 below.
24  *
25  * Redistributions in binary form must reproduce this Copyright Notice,
26  * these license terms, and the disclaimer/limitation of liability set
27  * forth as paragraph 6 below, in the documentation and/or other materials
28  * provided with the distribution.
29  *
30  * The Software is provided on an "AS IS" basis. No warranty is
31  * provided that the Software is free of defects, or fit for a
32  * particular purpose.
33  *
34  * Limitation of Liability. Quadcap Software shall not be liable
35  * for any damages suffered by the Licensee or any third party resulting
36  * from use of the Software.
37  */

38
39 package com.quadcap.crypto;
40
41 /*
42  * Public domain SHA implementation.
43  *
44  **/

45
46 // ---- Following is original comment from Chuck McManis's version:
47
// package util.crypt;
48
/*
49  * SHA1.java - An implementation of the SHA-1 Algorithm
50  *
51  * This version by Chuck McManis (cmcmanis@netcom.com) and
52  * still public domain.
53  *
54  * Based on the C code that Steve Reid wrote his header
55  * was :
56  * SHA-1 in C
57  * By Steve Reid <steve@edmweb.com>
58  * 100% Public Domain
59  *
60  * Test Vectors (from FIPS PUB 180-1)
61  * "abc"
62  * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
63  * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
64  * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
65  * A million repetitions of "a"
66  * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
67  */

68
69 import java.util.Random JavaDoc;
70
71 /**
72  * This is a simple port of Steve Reid's SHA-1 code into Java.
73  * I've run his test vectors through the code and they all pass.
74  *
75  */

76 public final class SHA1Digest implements Digest {
77     private byte[] digest = null;
78     private boolean digestValid = false;
79     private int[] state = new int[5];
80     private long count = 0;
81
82     /*
83      * The following array forms the basis for the transform
84      * buffer. Update puts bytes into this buffer and then
85      * transform adds it into the state of the digest.
86      */

87     private int[] block = new int[16];
88     private int blockIndex;
89
90     /**
91      * Default constructor
92      */

93     public SHA1Digest() {
94         init();
95     }
96
97     /**
98      *
99      * SHA1Init - Initialize new context
100      */

101     public void init() {
102         /* SHA1 initialization constants */
103         state[0] = 0x67452301;
104         state[1] = 0xEFCDAB89;
105         state[2] = 0x98BADCFE;
106         state[3] = 0x10325476;
107         state[4] = 0xC3D2E1F0;
108         count = 0;
109         digest = new byte[20];
110         digestValid = false;
111         blockIndex = 0;
112     }
113
114     /**
115      * Add one byte to the digest. When this is implemented
116      * all of the abstract class methods end up calling
117      * this method for types other than bytes.
118      */

119     public void update(byte b) {
120         int mask = (8 * (blockIndex & 3));
121         count += 8;
122         block[blockIndex >> 2] &= ~(0xff << mask);
123         block[blockIndex >> 2] |= (b & 0xff) << mask;
124         blockIndex++;
125         if (blockIndex == 64) {
126             transform();
127             blockIndex = 0;
128         }
129     }
130
131     /**
132      * Implementation for arrays just wraps the primitive byte operation
133      */

134     public void update(byte[] b, int off, int len) {
135         for (int i = 0; i < len; i++) update(b[off+i]);
136     }
137
138     /**
139      * And the full-array implementation is just a degenerate case of the
140      * array-subset implementation:
141      */

142     public void update(byte[] buf) { update(buf, 0, buf.length); }
143     
144     /**
145      * Return the message digest for the accumulated bytes
146      */

147     public byte[] digest() {
148         byte[] ret = null;
149         if (!digestValid) {
150             finish();
151             ret = digest;
152             init();
153         }
154         return ret;
155     }
156
157     /**
158      * Complete processing on the message digest.
159      */

160     private final void finish() {
161         byte bits[] = new byte[8];
162         int i, j;
163
164         for (i = 0; i < 8; i++) {
165             bits[i] = (byte)((count >>> (((7 - i) * 8))) & 0xff);
166         }
167
168         update((byte) 128);
169         while (blockIndex != 56)
170             update((byte) 0);
171         // This should cause a transform to happen.
172
update(bits);
173         for (i = 0; i < 20; i++) {
174             digest[i] = (byte)
175                 ((state[i>>2] >> ((3-(i & 3)) * 8) ) & 0xff);
176         }
177         digestValid = true;
178     }
179
180     /** Return a string that identifies this algorithm */
181     public String JavaDoc getAlg() { return "SHA1"; }
182
183     // ------------------------------------------------------------------
184
// private stuff
185

186
187     /*
188      * These functions are taken out of #defines in Steve's
189      * code. Java doesn't have a preprocessor so the first
190      * step is to just promote them to real methods.
191      * Later we can optimize them out into inline code,
192      * note that by making them final some compilers will
193      * inline them when given the -O flag.
194      */

195     final int rol(int value, int bits) {
196         int q = (value << bits) | (value >>> (32 - bits));
197         return q;
198     }
199
200     final int blk0(int i) {
201         block[i] = (rol(block[i],24)&0xFF00FF00) |
202             (rol(block[i],8)&0x00FF00FF);
203         return block[i];
204     }
205
206     final int blk(int i) {
207         block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15]^
208                           block[(i+2)&15]^block[i&15], 1);
209         return (block[i&15]);
210     }
211
212     final void R0(int data[], int v, int w, int x , int y, int z, int i) {
213         data[z] += ((data[w] & (data[x] ^ data[y] )) ^ data[y]) +
214             blk0(i) + 0x5A827999 + rol(data[v] ,5);
215         data[w] = rol(data[w], 30);
216     }
217
218     final void R1(int data[], int v, int w, int x, int y, int z, int i) {
219         data[z] += ((data[w] & (data[x] ^ data[y])) ^ data[y]) +
220             blk(i) + 0x5A827999 + rol(data[v] ,5);
221         data[w] = rol(data[w], 30);
222     }
223
224     final void R2(int data[], int v, int w, int x, int y, int z, int i) {
225         data[z] += (data[w] ^ data[x] ^ data[y]) +
226             blk(i) + 0x6ED9EBA1 + rol(data[v] ,5);
227         data[w] = rol(data[w], 30);
228     }
229
230     final void R3(int data[], int v, int w, int x, int y, int z, int i) {
231         data[z] += (((data[w] | data[x]) & data[y]) | (data[w] &
232                                                        data[x])) +
233             blk(i) + 0x8F1BBCDC + rol(data[v] ,5);
234         data[w] = rol(data[w], 30);
235     }
236
237     final void R4(int data[], int v, int w, int x, int y, int z, int i) {
238         data[z] += (data[w] ^ data[x] ^ data[y]) +
239             blk(i) + 0xCA62C1D6 + rol(data[v] ,5);
240         data[w] = rol(data[w], 30);
241     }
242
243
244     /*
245      * Steve's original code and comments :
246      *
247      * blk0() and blk() perform the initial expand.
248      * I got the idea of expanding during the round function from SSLeay
249      *
250      * #define blk0(i) block->l[i]
251      * #define blk(i) (block->l[i&15] =
252      rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
253      * ^block->l[(i+2)&15]^block->l[i&15],1))
254      *
255      * (R0+R1), R2, R3, R4 are the different operations used in SHA1
256      * #define R0(v,w,x,y,z,i)
257      z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
258      * #define R1(v,w,x,y,z,i)
259      z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
260      * #define R2(v,w,x,y,z,i)
261      z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
262      * #define R3(v,w,x,y,z,i)
263      z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
264      * #define R4(v,w,x,y,z,i)
265      z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
266     */

267
268     int dd[] = new int[5];
269
270     /**
271      * Hash a single 512-bit block. This is the core of the algorithm.
272      *
273      * Note that working with arrays is very inefficent in Java as it
274      * does a class cast check each time you store into the array.
275      *
276      */

277
278     void transform() {
279         /* Copy context->state[] to working vars */
280         dd[0] = state[0];
281         dd[1] = state[1];
282         dd[2] = state[2];
283         dd[3] = state[3];
284         dd[4] = state[4];
285         /* 4 rounds of 20 operations each. Loop unrolled. */
286         R0(dd,0,1,2,3,4, 0); R0(dd,4,0,1,2,3, 1); R0(dd,3,4,0,1,2, 2);
287         R0(dd,2,3,4,0,1, 3);
288         R0(dd,1,2,3,4,0, 4); R0(dd,0,1,2,3,4, 5); R0(dd,4,0,1,2,3, 6);
289         R0(dd,3,4,0,1,2, 7);
290         R0(dd,2,3,4,0,1, 8); R0(dd,1,2,3,4,0, 9); R0(dd,0,1,2,3,4,10);
291         R0(dd,4,0,1,2,3,11);
292         R0(dd,3,4,0,1,2,12); R0(dd,2,3,4,0,1,13); R0(dd,1,2,3,4,0,14);
293         R0(dd,0,1,2,3,4,15);
294         R1(dd,4,0,1,2,3,16); R1(dd,3,4,0,1,2,17); R1(dd,2,3,4,0,1,18);
295         R1(dd,1,2,3,4,0,19);
296         R2(dd,0,1,2,3,4,20); R2(dd,4,0,1,2,3,21); R2(dd,3,4,0,1,2,22);
297         R2(dd,2,3,4,0,1,23);
298         R2(dd,1,2,3,4,0,24); R2(dd,0,1,2,3,4,25); R2(dd,4,0,1,2,3,26);
299         R2(dd,3,4,0,1,2,27);
300         R2(dd,2,3,4,0,1,28); R2(dd,1,2,3,4,0,29); R2(dd,0,1,2,3,4,30);
301         R2(dd,4,0,1,2,3,31);
302         R2(dd,3,4,0,1,2,32); R2(dd,2,3,4,0,1,33); R2(dd,1,2,3,4,0,34);
303         R2(dd,0,1,2,3,4,35);
304         R2(dd,4,0,1,2,3,36); R2(dd,3,4,0,1,2,37); R2(dd,2,3,4,0,1,38);
305         R2(dd,1,2,3,4,0,39);
306         R3(dd,0,1,2,3,4,40); R3(dd,4,0,1,2,3,41); R3(dd,3,4,0,1,2,42);
307         R3(dd,2,3,4,0,1,43);
308         R3(dd,1,2,3,4,0,44); R3(dd,0,1,2,3,4,45); R3(dd,4,0,1,2,3,46);
309         R3(dd,3,4,0,1,2,47);
310         R3(dd,2,3,4,0,1,48); R3(dd,1,2,3,4,0,49); R3(dd,0,1,2,3,4,50);
311         R3(dd,4,0,1,2,3,51);
312         R3(dd,3,4,0,1,2,52); R3(dd,2,3,4,0,1,53); R3(dd,1,2,3,4,0,54);
313         R3(dd,0,1,2,3,4,55);
314         R3(dd,4,0,1,2,3,56); R3(dd,3,4,0,1,2,57); R3(dd,2,3,4,0,1,58);
315         R3(dd,1,2,3,4,0,59);
316         R4(dd,0,1,2,3,4,60); R4(dd,4,0,1,2,3,61); R4(dd,3,4,0,1,2,62);
317         R4(dd,2,3,4,0,1,63);
318         R4(dd,1,2,3,4,0,64); R4(dd,0,1,2,3,4,65); R4(dd,4,0,1,2,3,66);
319         R4(dd,3,4,0,1,2,67);
320         R4(dd,2,3,4,0,1,68); R4(dd,1,2,3,4,0,69); R4(dd,0,1,2,3,4,70);
321         R4(dd,4,0,1,2,3,71);
322         R4(dd,3,4,0,1,2,72); R4(dd,2,3,4,0,1,73); R4(dd,1,2,3,4,0,74);
323         R4(dd,0,1,2,3,4,75);
324         R4(dd,4,0,1,2,3,76); R4(dd,3,4,0,1,2,77); R4(dd,2,3,4,0,1,78);
325         R4(dd,1,2,3,4,0,79);
326         /* Add the working vars back into context.state[] */
327         state[0] += dd[0];
328         state[1] += dd[1];
329         state[2] += dd[2];
330         state[3] += dd[3];
331         state[4] += dd[4];
332     }
333
334     //#ifdef DEBUG
335
/**
336      * Print out the digest in a form that can be easily compared
337      * to the test vectors.
338      */

339     private String JavaDoc digout() {
340         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
341         for (int i = 0; i < 20; i++) {
342             char c1, c2;
343
344             c1 = (char) ((digest[i] >>> 4) & 0xf);
345             c2 = (char) (digest[i] & 0xf);
346             c1 = (char) ((c1 > 9) ? 'A' + (c1 - 10) : '0' + c1);
347             c2 = (char) ((c2 > 9) ? 'A' + (c2 - 10) : '0' + c2);
348             sb.append(c1);
349             sb.append(c2);
350             if (((i+1) % 4) == 0)
351                 sb.append(' ');
352         }
353         return sb.toString();
354     }
355
356
357     /**
358      * This is a test program for the SHA1 algorithm. It puts
359      * the three test vectors through the algorithm and prints
360      * out the results (they should match.) Then it runs the
361      * MessageDigest benchmark method to see how fast it is.
362      * on my P133 its about 110 - 120K bytes/second.
363      *
364      * It then compares it to MD5, which is about 150K bytes/second.
365      *
366      */

367     public static void main(String JavaDoc args[]) {
368         SHA1Digest s = new SHA1Digest();
369
370         System.out.println("SHA-1 Test PROGRAM.");
371         System.out.println("This code runs the test vectors through the code.");
372
373 /* "abc"
374         A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D */

375
376         System.out.println("First test is 'abc'");
377         String JavaDoc z = "abc";
378         s.init();
379         s.update((byte) 'a');
380         s.update((byte) 'b');
381         s.update((byte) 'c');
382         s.finish();
383         System.out.println(s.digout());
384         System.out.println("A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D");
385
386
387 /* "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
388         84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 */

389
390         System.out.println("Next Test is 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'");
391         z = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
392         s.init();
393         for (int j = 0; j < z.length(); j++) s.update((byte)z.charAt(j));
394         s.finish();
395         System.out.println(s.digout());
396         System.out.println("84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1");
397
398 /* A million repetitions of "a"
399         34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F */

400
401         System.out.println("Last test is 1 million 'a' characters.");
402         s.init();
403         for (int i = 0; i < 1000000; i++)
404             s.update((byte) 'a');
405         s.finish();
406         System.out.println(s.digout());
407         System.out.println("34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F");
408         //MessageDigest.benchmark(s);
409
//MD5 mm = new MD5();
410
//MessageDigest.benchmark(mm);
411
}
412     //#endif
413
}
414
Popular Tags