001: /* Copyright 2003 Quadcap Software. All rights reserved.
002: *
003: * This software is distributed under the Quadcap Free Software License.
004: * This software may be used or modified for any purpose, personal or
005: * commercial. Open Source redistributions are permitted. Commercial
006: * redistribution of larger works derived from, or works which bundle
007: * this software requires a "Commercial Redistribution License"; see
008: * http://www.quadcap.com/purchase.
009: *
010: * Redistributions qualify as "Open Source" under one of the following terms:
011: *
012: * Redistributions are made at no charge beyond the reasonable cost of
013: * materials and delivery.
014: *
015: * Redistributions are accompanied by a copy of the Source Code or by an
016: * irrevocable offer to provide a copy of the Source Code for up to three
017: * years at the cost of materials and delivery. Such redistributions
018: * must allow further use, modification, and redistribution of the Source
019: * Code under substantially the same terms as this license.
020: *
021: * Redistributions of source code must retain the copyright notices as they
022: * appear in each source code file, these license terms, and the
023: * disclaimer/limitation of liability set forth as paragraph 6 below.
024: *
025: * Redistributions in binary form must reproduce this Copyright Notice,
026: * these license terms, and the disclaimer/limitation of liability set
027: * forth as paragraph 6 below, in the documentation and/or other materials
028: * provided with the distribution.
029: *
030: * The Software is provided on an "AS IS" basis. No warranty is
031: * provided that the Software is free of defects, or fit for a
032: * particular purpose.
033: *
034: * Limitation of Liability. Quadcap Software shall not be liable
035: * for any damages suffered by the Licensee or any third party resulting
036: * from use of the Software.
037: */
038:
039: package com.quadcap.crypto;
040:
041: /*
042: * Public domain SHA implementation.
043: *
044: **/
045:
046: // ---- Following is original comment from Chuck McManis's version:
047: // package util.crypt;
048: /*
049: * SHA1.java - An implementation of the SHA-1 Algorithm
050: *
051: * This version by Chuck McManis (cmcmanis@netcom.com) and
052: * still public domain.
053: *
054: * Based on the C code that Steve Reid wrote his header
055: * was :
056: * SHA-1 in C
057: * By Steve Reid <steve@edmweb.com>
058: * 100% Public Domain
059: *
060: * Test Vectors (from FIPS PUB 180-1)
061: * "abc"
062: * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
063: * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
064: * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
065: * A million repetitions of "a"
066: * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
067: */
068:
069: import java.util.Random;
070:
071: /**
072: * This is a simple port of Steve Reid's SHA-1 code into Java.
073: * I've run his test vectors through the code and they all pass.
074: *
075: */
076: public final class SHA1Digest implements Digest {
077: private byte[] digest = null;
078: private boolean digestValid = false;
079: private int[] state = new int[5];
080: private long count = 0;
081:
082: /*
083: * The following array forms the basis for the transform
084: * buffer. Update puts bytes into this buffer and then
085: * transform adds it into the state of the digest.
086: */
087: private int[] block = new int[16];
088: private int blockIndex;
089:
090: /**
091: * Default constructor
092: */
093: public SHA1Digest() {
094: init();
095: }
096:
097: /**
098: *
099: * 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++)
136: update(b[off + i]);
137: }
138:
139: /**
140: * And the full-array implementation is just a degenerate case of the
141: * array-subset implementation:
142: */
143: public void update(byte[] buf) {
144: update(buf, 0, buf.length);
145: }
146:
147: /**
148: * Return the message digest for the accumulated bytes
149: */
150: public byte[] digest() {
151: byte[] ret = null;
152: if (!digestValid) {
153: finish();
154: ret = digest;
155: init();
156: }
157: return ret;
158: }
159:
160: /**
161: * Complete processing on the message digest.
162: */
163: private final void finish() {
164: byte bits[] = new byte[8];
165: int i, j;
166:
167: for (i = 0; i < 8; i++) {
168: bits[i] = (byte) ((count >>> (((7 - i) * 8))) & 0xff);
169: }
170:
171: update((byte) 128);
172: while (blockIndex != 56)
173: update((byte) 0);
174: // This should cause a transform to happen.
175: update(bits);
176: for (i = 0; i < 20; i++) {
177: digest[i] = (byte) ((state[i >> 2] >> ((3 - (i & 3)) * 8)) & 0xff);
178: }
179: digestValid = true;
180: }
181:
182: /** Return a string that identifies this algorithm */
183: public String getAlg() {
184: return "SHA1";
185: }
186:
187: // ------------------------------------------------------------------
188: // private stuff
189:
190: /*
191: * These functions are taken out of #defines in Steve's
192: * code. Java doesn't have a preprocessor so the first
193: * step is to just promote them to real methods.
194: * Later we can optimize them out into inline code,
195: * note that by making them final some compilers will
196: * inline them when given the -O flag.
197: */
198: final int rol(int value, int bits) {
199: int q = (value << bits) | (value >>> (32 - bits));
200: return q;
201: }
202:
203: final int blk0(int i) {
204: block[i] = (rol(block[i], 24) & 0xFF00FF00)
205: | (rol(block[i], 8) & 0x00FF00FF);
206: return block[i];
207: }
208:
209: final int blk(int i) {
210: block[i & 15] = rol(block[(i + 13) & 15] ^ block[(i + 8) & 15]
211: ^ block[(i + 2) & 15] ^ block[i & 15], 1);
212: return (block[i & 15]);
213: }
214:
215: final void R0(int data[], int v, int w, int x, int y, int z, int i) {
216: data[z] += ((data[w] & (data[x] ^ data[y])) ^ data[y])
217: + blk0(i) + 0x5A827999 + rol(data[v], 5);
218: data[w] = rol(data[w], 30);
219: }
220:
221: final void R1(int data[], int v, int w, int x, int y, int z, int i) {
222: data[z] += ((data[w] & (data[x] ^ data[y])) ^ data[y]) + blk(i)
223: + 0x5A827999 + rol(data[v], 5);
224: data[w] = rol(data[w], 30);
225: }
226:
227: final void R2(int data[], int v, int w, int x, int y, int z, int i) {
228: data[z] += (data[w] ^ data[x] ^ data[y]) + blk(i) + 0x6ED9EBA1
229: + rol(data[v], 5);
230: data[w] = rol(data[w], 30);
231: }
232:
233: final void R3(int data[], int v, int w, int x, int y, int z, int i) {
234: data[z] += (((data[w] | data[x]) & data[y]) | (data[w] & data[x]))
235: + blk(i) + 0x8F1BBCDC + rol(data[v], 5);
236: data[w] = rol(data[w], 30);
237: }
238:
239: final void R4(int data[], int v, int w, int x, int y, int z, int i) {
240: data[z] += (data[w] ^ data[x] ^ data[y]) + blk(i) + 0xCA62C1D6
241: + rol(data[v], 5);
242: data[w] = rol(data[w], 30);
243: }
244:
245: /*
246: * Steve's original code and comments :
247: *
248: * blk0() and blk() perform the initial expand.
249: * I got the idea of expanding during the round function from SSLeay
250: *
251: * #define blk0(i) block->l[i]
252: * #define blk(i) (block->l[i&15] =
253: rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
254: * ^block->l[(i+2)&15]^block->l[i&15],1))
255: *
256: * (R0+R1), R2, R3, R4 are the different operations used in SHA1
257: * #define R0(v,w,x,y,z,i)
258: z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
259: * #define R1(v,w,x,y,z,i)
260: z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
261: * #define R2(v,w,x,y,z,i)
262: z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
263: * #define R3(v,w,x,y,z,i)
264: z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
265: * #define R4(v,w,x,y,z,i)
266: z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
267: */
268:
269: int dd[] = new int[5];
270:
271: /**
272: * Hash a single 512-bit block. This is the core of the algorithm.
273: *
274: * Note that working with arrays is very inefficent in Java as it
275: * does a class cast check each time you store into the array.
276: *
277: */
278:
279: void transform() {
280: /* Copy context->state[] to working vars */
281: dd[0] = state[0];
282: dd[1] = state[1];
283: dd[2] = state[2];
284: dd[3] = state[3];
285: dd[4] = state[4];
286: /* 4 rounds of 20 operations each. Loop unrolled. */
287: R0(dd, 0, 1, 2, 3, 4, 0);
288: R0(dd, 4, 0, 1, 2, 3, 1);
289: R0(dd, 3, 4, 0, 1, 2, 2);
290: R0(dd, 2, 3, 4, 0, 1, 3);
291: R0(dd, 1, 2, 3, 4, 0, 4);
292: R0(dd, 0, 1, 2, 3, 4, 5);
293: R0(dd, 4, 0, 1, 2, 3, 6);
294: R0(dd, 3, 4, 0, 1, 2, 7);
295: R0(dd, 2, 3, 4, 0, 1, 8);
296: R0(dd, 1, 2, 3, 4, 0, 9);
297: R0(dd, 0, 1, 2, 3, 4, 10);
298: R0(dd, 4, 0, 1, 2, 3, 11);
299: R0(dd, 3, 4, 0, 1, 2, 12);
300: R0(dd, 2, 3, 4, 0, 1, 13);
301: R0(dd, 1, 2, 3, 4, 0, 14);
302: R0(dd, 0, 1, 2, 3, 4, 15);
303: R1(dd, 4, 0, 1, 2, 3, 16);
304: R1(dd, 3, 4, 0, 1, 2, 17);
305: R1(dd, 2, 3, 4, 0, 1, 18);
306: R1(dd, 1, 2, 3, 4, 0, 19);
307: R2(dd, 0, 1, 2, 3, 4, 20);
308: R2(dd, 4, 0, 1, 2, 3, 21);
309: R2(dd, 3, 4, 0, 1, 2, 22);
310: R2(dd, 2, 3, 4, 0, 1, 23);
311: R2(dd, 1, 2, 3, 4, 0, 24);
312: R2(dd, 0, 1, 2, 3, 4, 25);
313: R2(dd, 4, 0, 1, 2, 3, 26);
314: R2(dd, 3, 4, 0, 1, 2, 27);
315: R2(dd, 2, 3, 4, 0, 1, 28);
316: R2(dd, 1, 2, 3, 4, 0, 29);
317: R2(dd, 0, 1, 2, 3, 4, 30);
318: R2(dd, 4, 0, 1, 2, 3, 31);
319: R2(dd, 3, 4, 0, 1, 2, 32);
320: R2(dd, 2, 3, 4, 0, 1, 33);
321: R2(dd, 1, 2, 3, 4, 0, 34);
322: R2(dd, 0, 1, 2, 3, 4, 35);
323: R2(dd, 4, 0, 1, 2, 3, 36);
324: R2(dd, 3, 4, 0, 1, 2, 37);
325: R2(dd, 2, 3, 4, 0, 1, 38);
326: R2(dd, 1, 2, 3, 4, 0, 39);
327: R3(dd, 0, 1, 2, 3, 4, 40);
328: R3(dd, 4, 0, 1, 2, 3, 41);
329: R3(dd, 3, 4, 0, 1, 2, 42);
330: R3(dd, 2, 3, 4, 0, 1, 43);
331: R3(dd, 1, 2, 3, 4, 0, 44);
332: R3(dd, 0, 1, 2, 3, 4, 45);
333: R3(dd, 4, 0, 1, 2, 3, 46);
334: R3(dd, 3, 4, 0, 1, 2, 47);
335: R3(dd, 2, 3, 4, 0, 1, 48);
336: R3(dd, 1, 2, 3, 4, 0, 49);
337: R3(dd, 0, 1, 2, 3, 4, 50);
338: R3(dd, 4, 0, 1, 2, 3, 51);
339: R3(dd, 3, 4, 0, 1, 2, 52);
340: R3(dd, 2, 3, 4, 0, 1, 53);
341: R3(dd, 1, 2, 3, 4, 0, 54);
342: R3(dd, 0, 1, 2, 3, 4, 55);
343: R3(dd, 4, 0, 1, 2, 3, 56);
344: R3(dd, 3, 4, 0, 1, 2, 57);
345: R3(dd, 2, 3, 4, 0, 1, 58);
346: R3(dd, 1, 2, 3, 4, 0, 59);
347: R4(dd, 0, 1, 2, 3, 4, 60);
348: R4(dd, 4, 0, 1, 2, 3, 61);
349: R4(dd, 3, 4, 0, 1, 2, 62);
350: R4(dd, 2, 3, 4, 0, 1, 63);
351: R4(dd, 1, 2, 3, 4, 0, 64);
352: R4(dd, 0, 1, 2, 3, 4, 65);
353: R4(dd, 4, 0, 1, 2, 3, 66);
354: R4(dd, 3, 4, 0, 1, 2, 67);
355: R4(dd, 2, 3, 4, 0, 1, 68);
356: R4(dd, 1, 2, 3, 4, 0, 69);
357: R4(dd, 0, 1, 2, 3, 4, 70);
358: R4(dd, 4, 0, 1, 2, 3, 71);
359: R4(dd, 3, 4, 0, 1, 2, 72);
360: R4(dd, 2, 3, 4, 0, 1, 73);
361: R4(dd, 1, 2, 3, 4, 0, 74);
362: R4(dd, 0, 1, 2, 3, 4, 75);
363: R4(dd, 4, 0, 1, 2, 3, 76);
364: R4(dd, 3, 4, 0, 1, 2, 77);
365: R4(dd, 2, 3, 4, 0, 1, 78);
366: R4(dd, 1, 2, 3, 4, 0, 79);
367: /* Add the working vars back into context.state[] */
368: state[0] += dd[0];
369: state[1] += dd[1];
370: state[2] += dd[2];
371: state[3] += dd[3];
372: state[4] += dd[4];
373: }
374:
375: //#ifdef DEBUG
376: /**
377: * Print out the digest in a form that can be easily compared
378: * to the test vectors.
379: */
380: private String digout() {
381: StringBuffer sb = new StringBuffer();
382: for (int i = 0; i < 20; i++) {
383: char c1, c2;
384:
385: c1 = (char) ((digest[i] >>> 4) & 0xf);
386: c2 = (char) (digest[i] & 0xf);
387: c1 = (char) ((c1 > 9) ? 'A' + (c1 - 10) : '0' + c1);
388: c2 = (char) ((c2 > 9) ? 'A' + (c2 - 10) : '0' + c2);
389: sb.append(c1);
390: sb.append(c2);
391: if (((i + 1) % 4) == 0)
392: sb.append(' ');
393: }
394: return sb.toString();
395: }
396:
397: /**
398: * This is a test program for the SHA1 algorithm. It puts
399: * the three test vectors through the algorithm and prints
400: * out the results (they should match.) Then it runs the
401: * MessageDigest benchmark method to see how fast it is.
402: * on my P133 its about 110 - 120K bytes/second.
403: *
404: * It then compares it to MD5, which is about 150K bytes/second.
405: *
406: */
407: public static void main(String args[]) {
408: SHA1Digest s = new SHA1Digest();
409:
410: System.out.println("SHA-1 Test PROGRAM.");
411: System.out
412: .println("This code runs the test vectors through the code.");
413:
414: /* "abc"
415: A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D */
416:
417: System.out.println("First test is 'abc'");
418: String z = "abc";
419: s.init();
420: s.update((byte) 'a');
421: s.update((byte) 'b');
422: s.update((byte) 'c');
423: s.finish();
424: System.out.println(s.digout());
425: System.out
426: .println("A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D");
427:
428: /* "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
429: 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 */
430:
431: System.out
432: .println("Next Test is 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'");
433: z = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
434: s.init();
435: for (int j = 0; j < z.length(); j++)
436: s.update((byte) z.charAt(j));
437: s.finish();
438: System.out.println(s.digout());
439: System.out
440: .println("84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1");
441:
442: /* A million repetitions of "a"
443: 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F */
444:
445: System.out.println("Last test is 1 million 'a' characters.");
446: s.init();
447: for (int i = 0; i < 1000000; i++)
448: s.update((byte) 'a');
449: s.finish();
450: System.out.println(s.digout());
451: System.out
452: .println("34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F");
453: //MessageDigest.benchmark(s);
454: //MD5 mm = new MD5();
455: //MessageDigest.benchmark(mm);
456: }
457: //#endif
458: }
|