Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/ssttr/crypto/SHA1.java


1   /*
2    * SHA1.java - An implementation of the SHA-1 Algorithm
3    *
4    * This version by Chuck McManis (cmcmanis@netcom.com) and
5    * still public domain.
6    *
7    * Based on the C code that Steve Reid wrote his header
8    * was :
9    *      SHA-1 in C
10   *      By Steve Reid <steve@edmweb.com>
11   *      100% Public Domain
12   *
13   *      Test Vectors (from FIPS PUB 180-1)
14   *      "abc"
15   *      A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
16   *      "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
17   *      84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
18   *      A million repetitions of "a"
19   *      34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
20   * 
21   * This file was obtained from: http://www.mcmanis.com/~cmcmanis/java/src/util/crypt/SHA1.java
22   * More information can be found here: http://www.mcmanis.com/~cmcmanis/java/
23   */
24  
25  package com.ssttr.crypto;
26  
27  /**
28   * This is a simple port of Steve Reid's SHA-1 code into Java.
29   * I've run his test vectors through the code and they all pass.
30   *
31   */
32  public final class SHA1 extends MessageDigest {
33      private int state[] = new int[5];
34      private long count;
35  
36  
37      public SHA1() {
38          state = new int[5];
39          count = 0;
40          if (block == null)
41              block = new int[16];
42          digestBits = new byte[20];
43          digestValid = false;
44      }
45  
46      /*
47       * The following array forms the basis for the transform
48       * buffer. Update puts bytes into this buffer and then
49       * transform adds it into the state of the digest.
50       */
51      private int block[] = new int[16];
52      private int blockIndex;
53  
54      /*
55       * These functions are taken out of #defines in Steve's
56       * code. Java doesn't have a preprocessor so the first
57       * step is to just promote them to real methods.
58       * Later we can optimize them out into inline code,
59       * note that by making them final some compilers will
60       * inline them when given the -O flag.
61       */
62      final int rol(int value, int bits) {
63          int q = (value << bits) | (value >>> (32 - bits));
64          return q;
65      }
66  
67      final int blk0(int i) {
68          block[i] = (rol(block[i],24)&0xFF00FF00) | (rol(block[i],8)&0x00FF00FF);
69          return block[i];
70      }
71  
72      final int blk(int i) {
73          block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15]^
74                            block[(i+2)&15]^block[i&15], 1);
75          return (block[i&15]);
76      }
77  
78      final void R0(int data[], int v, int w, int x , int y, int z, int i) {
79          data[z] += ((data[w] & (data[x] ^ data[y] )) ^ data[y]) +
80                                  blk0(i) + 0x5A827999 + rol(data[v] ,5);
81          data[w] = rol(data[w], 30);
82      }
83  
84      final void R1(int data[], int v, int w, int x, int y, int z, int i) {
85          data[z] += ((data[w] & (data[x] ^ data[y])) ^ data[y]) +
86                                  blk(i) + 0x5A827999 + rol(data[v] ,5);
87          data[w] = rol(data[w], 30);
88      }
89  
90      final void R2(int data[], int v, int w, int x, int y, int z, int i) {
91          data[z] += (data[w] ^ data[x] ^ data[y]) +
92                                  blk(i) + 0x6ED9EBA1 + rol(data[v] ,5);
93          data[w] = rol(data[w], 30);
94      }
95  
96      final void R3(int data[], int v, int w, int x, int y, int z, int i) {
97          data[z] += (((data[w] | data[x]) & data[y]) | (data[w] & data[x])) +
98                                  blk(i) + 0x8F1BBCDC + rol(data[v] ,5);
99          data[w] = rol(data[w], 30);
100     }
101 
102     final void R4(int data[], int v, int w, int x, int y, int z, int i) {
103         data[z] += (data[w] ^ data[x] ^ data[y]) +
104                                 blk(i) + 0xCA62C1D6 + rol(data[v] ,5);
105         data[w] = rol(data[w], 30);
106     }
107 
108 
109     /*
110      * Steve's original code and comments :
111      *
112      * blk0() and blk() perform the initial expand.
113      * I got the idea of expanding during the round function from SSLeay
114      *
115      * #define blk0(i) block->l[i]
116      * #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
117      *   ^block->l[(i+2)&15]^block->l[i&15],1))
118      *
119      * (R0+R1), R2, R3, R4 are the different operations used in SHA1
120      * #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
121      * #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
122      * #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
123      * #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
124      * #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
125      */
126 
127     int dd[] = new int[5];
128 
129     /**
130      * Hash a single 512-bit block. This is the core of the algorithm.
131      *
132      * Note that working with arrays is very inefficent in Java as it
133      * does a class cast check each time you store into the array.
134      *
135      */
136 
137     void transform() {
138 
139         /* Copy context->state[] to working vars */
140         dd[0] = state[0];
141         dd[1] = state[1];
142         dd[2] = state[2];
143         dd[3] = state[3];
144         dd[4] = state[4];
145         /* 4 rounds of 20 operations each. Loop unrolled. */
146         R0(dd,0,1,2,3,4, 0); R0(dd,4,0,1,2,3, 1); R0(dd,3,4,0,1,2, 2); R0(dd,2,3,4,0,1, 3);
147         R0(dd,1,2,3,4,0, 4); R0(dd,0,1,2,3,4, 5); R0(dd,4,0,1,2,3, 6); R0(dd,3,4,0,1,2, 7);
148         R0(dd,2,3,4,0,1, 8); R0(dd,1,2,3,4,0, 9); R0(dd,0,1,2,3,4,10); R0(dd,4,0,1,2,3,11);
149         R0(dd,3,4,0,1,2,12); R0(dd,2,3,4,0,1,13); R0(dd,1,2,3,4,0,14); R0(dd,0,1,2,3,4,15);
150         R1(dd,4,0,1,2,3,16); R1(dd,3,4,0,1,2,17); R1(dd,2,3,4,0,1,18); R1(dd,1,2,3,4,0,19);
151         R2(dd,0,1,2,3,4,20); R2(dd,4,0,1,2,3,21); R2(dd,3,4,0,1,2,22); R2(dd,2,3,4,0,1,23);
152         R2(dd,1,2,3,4,0,24); R2(dd,0,1,2,3,4,25); R2(dd,4,0,1,2,3,26); R2(dd,3,4,0,1,2,27);
153         R2(dd,2,3,4,0,1,28); R2(dd,1,2,3,4,0,29); R2(dd,0,1,2,3,4,30); R2(dd,4,0,1,2,3,31);
154         R2(dd,3,4,0,1,2,32); R2(dd,2,3,4,0,1,33); R2(dd,1,2,3,4,0,34); R2(dd,0,1,2,3,4,35);
155         R2(dd,4,0,1,2,3,36); R2(dd,3,4,0,1,2,37); R2(dd,2,3,4,0,1,38); R2(dd,1,2,3,4,0,39);
156         R3(dd,0,1,2,3,4,40); R3(dd,4,0,1,2,3,41); R3(dd,3,4,0,1,2,42); R3(dd,2,3,4,0,1,43);
157         R3(dd,1,2,3,4,0,44); R3(dd,0,1,2,3,4,45); R3(dd,4,0,1,2,3,46); R3(dd,3,4,0,1,2,47);
158         R3(dd,2,3,4,0,1,48); R3(dd,1,2,3,4,0,49); R3(dd,0,1,2,3,4,50); R3(dd,4,0,1,2,3,51);
159         R3(dd,3,4,0,1,2,52); R3(dd,2,3,4,0,1,53); R3(dd,1,2,3,4,0,54); R3(dd,0,1,2,3,4,55);
160         R3(dd,4,0,1,2,3,56); R3(dd,3,4,0,1,2,57); R3(dd,2,3,4,0,1,58); R3(dd,1,2,3,4,0,59);
161         R4(dd,0,1,2,3,4,60); R4(dd,4,0,1,2,3,61); R4(dd,3,4,0,1,2,62); R4(dd,2,3,4,0,1,63);
162         R4(dd,1,2,3,4,0,64); R4(dd,0,1,2,3,4,65); R4(dd,4,0,1,2,3,66); R4(dd,3,4,0,1,2,67);
163         R4(dd,2,3,4,0,1,68); R4(dd,1,2,3,4,0,69); R4(dd,0,1,2,3,4,70); R4(dd,4,0,1,2,3,71);
164         R4(dd,3,4,0,1,2,72); R4(dd,2,3,4,0,1,73); R4(dd,1,2,3,4,0,74); R4(dd,0,1,2,3,4,75);
165         R4(dd,4,0,1,2,3,76); R4(dd,3,4,0,1,2,77); R4(dd,2,3,4,0,1,78); R4(dd,1,2,3,4,0,79);
166         /* Add the working vars back into context.state[] */
167         state[0] += dd[0];
168         state[1] += dd[1];
169         state[2] += dd[2];
170         state[3] += dd[3];
171         state[4] += dd[4];
172     }
173 
174 
175     /**
176      *
177      * SHA1Init - Initialize new context
178      */
179     public void init() {
180         /* SHA1 initialization constants */
181         state[0] = 0x67452301;
182         state[1] = 0xEFCDAB89;
183         state[2] = 0x98BADCFE;
184         state[3] = 0x10325476;
185         state[4] = 0xC3D2E1F0;
186         count = 0;
187         digestBits = new byte[20];
188         digestValid = false;
189         blockIndex = 0;
190     }
191 
192     /**
193      * Add one byte to the digest. When this is implemented
194      * all of the abstract class methods end up calling
195      * this method for types other than bytes.
196      */
197     public synchronized void update(byte b) {
198         int mask = (8 * (blockIndex & 3));
199 
200         count += 8;
201         block[blockIndex >> 2] &= ~(0xff << mask);
202         block[blockIndex >> 2] |= (b & 0xff) << mask;
203         blockIndex++;
204         if (blockIndex == 64) {
205             transform();
206             blockIndex = 0;
207         }
208     }
209 
210 
211     /**
212      * Complete processing on the message digest.
213      */
214     public void finish() {
215         byte bits[] = new byte[8];
216         int i;
217 
218         for (i = 0; i < 8; i++) {
219             bits[i] = (byte)((count >>> (((7 - i) * 8))) & 0xff);
220         }
221 
222         update((byte) 128);
223         while (blockIndex != 56)
224             update((byte) 0);
225         // This should cause a transform to happen.
226         update(bits);
227         for (i = 0; i < 20; i++) {
228             digestBits[i] = (byte)
229                 ((state[i>>2] >> ((3-(i & 3)) * 8) ) & 0xff);
230         }
231         digestValid = true;
232     }
233 
234     /** Return a string that identifies this algorithm */
235     public String getAlg() { return "SHA1"; }
236 
237     /**
238      * Print out the digest in a form that can be easily compared
239      * to the test vectors.
240      */
241     /*
242     private String digout() {
243         StringBuffer sb = new StringBuffer();
244         for (int i = 0; i < 20; i++) {
245             char c1, c2;
246 
247             c1 = (char) ((digestBits[i] >>> 4) & 0xf);
248             c2 = (char) (digestBits[i] & 0xf);
249             c1 = (char) ((c1 > 9) ? 'A' + (c1 - 10) : '0' + c1);
250             c2 = (char) ((c2 > 9) ? 'A' + (c2 - 10) : '0' + c2);
251             sb.append(c1);
252             sb.append(c2);
253             if (((i+1) % 4) == 0)
254                 sb.append(' ');
255         }
256         return sb.toString();
257     }
258    */
259 
260     /**
261      * This is a test program for the SHA1 algorithm. It puts
262      * the three test vectors through the algorithm and prints
263      * out the results (they should match.) Then it runs the
264      * MessageDigest benchmark method to see how fast it is.
265      * on my P133 its about 110 - 120K bytes/second.
266      *
267      * It then compares it to MD5, which is about 150K bytes/second.
268      *
269      * The reference to MoreOutputStream can be deleted. This is a
270      * small class that opens a window to display the results. This
271      * works around Symantec Cafe's tendency to shut down the DOS
272      * window after showing the output, and the inability to scroll
273      * back in a DOS window.
274      */
275 
276 /*
277     public static void main(String args[]) {
278         int i, j;
279         SHA1 s = new SHA1();
280         // This line may be safely deleted, its to make it easy to see
281         // the output of the program.
282         System.out = new java.io.PrintStream(new util.MoreOutputStream());
283 
284 
285         System.out.println("SHA-1 Test PROGRAM.");
286         System.out.println("This code runs the test vectors through the code.");
287 
288 //      "abc"
289 //        A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D 
290 
291         System.out.println("First test is 'abc'");
292         String z = "abc";
293         s.init();
294         s.update((byte) 'a');
295         s.update((byte) 'b');
296         s.update((byte) 'c');
297         s.finish();
298         System.out.println(s.digout());
299         System.out.println("A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D");
300 
301 
302 //      "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
303 //        84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 
304 
305         System.out.println("Next Test is 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'");
306         z = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
307         s.init();
308         s.updateASCII(z);
309         s.finish();
310         System.out.println(s.digout());
311         System.out.println("84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1");
312 
313 //      A million repetitions of "a"
314 //        34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F 
315 
316         System.out.println("Last test is 1 million 'a' characters.");
317         s.init();
318         for (i = 0; i < 1000000; i++)
319             s.update((byte) 'a');
320         s.finish();
321         System.out.println(s.digout());
322         System.out.println("34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F");
323         MessageDigest.benchmark(s);
324         MD5 mm = new MD5();
325         MessageDigest.benchmark(mm);
326     }
327 */
328     
329 }