001: /*
002: * @(#)SHA.java 1.42 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package sun.security.provider;
029:
030: import java.security.*;
031:
032: /**
033: * This class implements the Secure Hash Algorithm (SHA) developed by
034: * the National Institute of Standards and Technology along with the
035: * National Security Agency. This is the updated version of SHA
036: * fip-180 as superseded by fip-180-1.
037: *
038: * <p>It implement JavaSecurity MessageDigest, and can be used by in
039: * the Java Security framework, as a pluggable implementation, as a
040: * filter for the digest stream classes.
041: *
042: * @version 1.35 02/02/00
043: * @author Roger Riggs
044: * @author Benjamin Renaud
045: */
046:
047: public class SHA extends MessageDigestSpi implements Cloneable {
048:
049: /* This private hookm controlled by the appropriate constructor,
050: causes this class to implement the first version of SHA,
051: as defined in FIPS 180, as opposed to FIPS 180-1. This was
052: useful for DSA testing. */
053: private int version = 1;
054:
055: private static final int SHA_LENGTH = 20;
056:
057: // Buffer of int's and count of characters accumulated
058: // 64 bytes are included in each hash block so the low order
059: // bits of count are used to know how to pack the bytes into ints
060: // and to know when to compute the block and start the next one.
061: private int W[] = new int[80];
062: private long count = 0;
063: private final int countmax = 64;
064: private final int countmask = (countmax - 1);
065:
066: private int AA, BB, CC, DD, EE;
067:
068: /**
069: * Creates a SHA object.with state (for cloning) */
070: private SHA(SHA sha) {
071: this ();
072: this .version = sha.version;
073: System.arraycopy(sha.W, 0, this .W, 0, W.length);
074: this .count = sha.count;
075: this .AA = sha.AA;
076: this .BB = sha.BB;
077: this .CC = sha.CC;
078: this .DD = sha.DD;
079: this .EE = sha.EE;
080: }
081:
082: SHA(int version) {
083: this ();
084: this .version = version;
085: }
086:
087: /**
088: * Creates a new SHA object.
089: */
090: public SHA() {
091: init();
092: }
093:
094: /**
095: * Return the length of the digest in bytes
096: */
097: protected int engineGetDigestLength() {
098: return (SHA_LENGTH);
099: }
100:
101: public void engineUpdate(byte b) {
102: engineUpdate((int) b);
103: }
104:
105: /**
106: * Update a byte.
107: *
108: * @param b the byte
109: */
110: private void engineUpdate(int b) {
111: int word;
112: int offset;
113:
114: /* compute word offset and bit offset within word the low bits
115: of count are inverted to make put the bytes in the write
116: order */
117: word = ((int) count & countmask) >>> 2;
118: offset = (~(int) count & 3) << 3;
119:
120: W[word] = (W[word] & ~(0xff << offset))
121: | ((b & 0xff) << offset);
122:
123: /* If this is the last byte of a block, compute the partial hash */
124: if (((int) count & countmask) == countmask) {
125: computeBlock();
126: }
127: count++;
128: }
129:
130: /**
131: * Update a buffer.
132: *
133: * @param b the data to be updated.
134: * @param off the start offset in the data
135: * @param len the number of bytes to be updated.
136: */
137: public void engineUpdate(byte b[], int off, int len) {
138: int word;
139: int offset;
140:
141: if ((off < 0) || (len < 0) || (off + len > b.length))
142: throw new ArrayIndexOutOfBoundsException();
143:
144: // Use single writes until integer aligned
145: while ((len > 0) && ((int) count & 3) != 0) {
146: engineUpdate(b[off]);
147: off++;
148: len--;
149: }
150:
151: /* Assemble groups of 4 bytes to be inserted in integer array */
152: for (; len >= 4; len -= 4, off += 4) {
153:
154: word = ((int) count & countmask) >> 2;
155:
156: W[word] = ((b[off] & 0xff) << 24)
157: | ((b[off + 1] & 0xff) << 16)
158: | ((b[off + 2] & 0xff) << 8)
159: | ((b[off + 3] & 0xff));
160:
161: count += 4;
162: if (((int) count & countmask) == 0) {
163: computeBlock();
164: }
165: }
166:
167: /* Use single writes for last few bytes */
168: for (; len > 0; len--, off++) {
169: engineUpdate(b[off]);
170: }
171: }
172:
173: /**
174: * Resets the buffers and hash value to start a new hash.
175: */
176: public void init() {
177: AA = 0x67452301;
178: BB = 0xefcdab89;
179: CC = 0x98badcfe;
180: DD = 0x10325476;
181: EE = 0xc3d2e1f0;
182:
183: for (int i = 0; i < 80; i++)
184: W[i] = 0;
185: count = 0;
186: }
187:
188: /**
189: * Resets the buffers and hash value to start a new hash.
190: */
191: public void engineReset() {
192: init();
193: }
194:
195: /**
196: * Computes the final hash and returns the final value as a
197: * byte[20] array. The object is reset to be ready for further
198: * use, as specified in the JavaSecurity MessageDigest
199: * specification. */
200: public byte[] engineDigest() {
201: byte hashvalue[] = new byte[SHA_LENGTH];
202:
203: try {
204: engineDigest(hashvalue, 0, hashvalue.length);
205: } catch (DigestException e) {
206: throw new InternalError("");
207: }
208: return hashvalue;
209: }
210:
211: /**
212: * Computes the final hash and returns the final value as a
213: * byte[20] array. The object is reset to be ready for further
214: * use, as specified in the JavaSecurity MessageDigest
215: * specification. */
216: public int engineDigest(byte[] hashvalue, int offset, int len)
217: throws DigestException {
218:
219: if (len < SHA_LENGTH)
220: throw new DigestException("partial digests not returned");
221: if (hashvalue.length - offset < SHA_LENGTH)
222: throw new DigestException(
223: "insufficient space in the output "
224: + "buffer to store the digest");
225:
226: /* The number of bits before padding occurs */
227: long bits = count << 3;
228:
229: engineUpdate(0x80);
230:
231: /* Pad with zeros until length is a multiple of 448 (the last two
232: 32 ints are used a holder for bits (see above). */
233: while ((int) (count & countmask) != 56) {
234: engineUpdate(0);
235: }
236:
237: W[14] = (int) (bits >>> 32);
238: W[15] = (int) (bits & 0xffffffff);
239:
240: count += 8;
241: computeBlock();
242:
243: // Copy out the result
244: hashvalue[offset + 0] = (byte) (AA >>> 24);
245: hashvalue[offset + 1] = (byte) (AA >>> 16);
246: hashvalue[offset + 2] = (byte) (AA >>> 8);
247: hashvalue[offset + 3] = (byte) (AA >>> 0);
248:
249: hashvalue[offset + 4] = (byte) (BB >>> 24);
250: hashvalue[offset + 5] = (byte) (BB >>> 16);
251: hashvalue[offset + 6] = (byte) (BB >>> 8);
252: hashvalue[offset + 7] = (byte) (BB >>> 0);
253:
254: hashvalue[offset + 8] = (byte) (CC >>> 24);
255: hashvalue[offset + 9] = (byte) (CC >>> 16);
256: hashvalue[offset + 10] = (byte) (CC >>> 8);
257: hashvalue[offset + 11] = (byte) (CC >>> 0);
258:
259: hashvalue[offset + 12] = (byte) (DD >>> 24);
260: hashvalue[offset + 13] = (byte) (DD >>> 16);
261: hashvalue[offset + 14] = (byte) (DD >>> 8);
262: hashvalue[offset + 15] = (byte) (DD >>> 0);
263:
264: hashvalue[offset + 16] = (byte) (EE >>> 24);
265: hashvalue[offset + 17] = (byte) (EE >>> 16);
266: hashvalue[offset + 18] = (byte) (EE >>> 8);
267: hashvalue[offset + 19] = (byte) (EE >>> 0);
268:
269: engineReset(); // remove the evidence
270:
271: return SHA_LENGTH;
272: }
273:
274: // Constants for each round
275: private final int round1_kt = 0x5a827999;
276: private final int round2_kt = 0x6ed9eba1;
277: private final int round3_kt = 0x8f1bbcdc;
278: private final int round4_kt = 0xca62c1d6;
279:
280: /**
281: * Compute a the hash for the current block.
282: *
283: * This is in the same vein as Peter Gutmann's algorithm listed in
284: * the back of Applied Cryptography, Compact implementation of
285: * "old" NIST Secure Hash Algorithm.
286: *
287: */
288: private void computeBlock() {
289: int temp, a, b, c, d, e;
290:
291: // The first 16 ints have the byte stream, compute the rest of
292: // the buffer
293: for (int t = 16; t <= 79; t++) {
294: if (version == 0) {
295: W[t] = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16];
296: } else {
297: temp = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16];
298: W[t] = ((temp << 1) | (temp >>> (32 - 1)));
299: }
300: }
301:
302: a = AA;
303: b = BB;
304: c = CC;
305: d = DD;
306: e = EE;
307:
308: // Round 1
309: for (int i = 0; i < 20; i++) {
310: temp = ((a << 5) | (a >>> (32 - 5)))
311: + ((b & c) | ((~b) & d)) + e + W[i] + round1_kt;
312: e = d;
313: d = c;
314: c = ((b << 30) | (b >>> (32 - 30)));
315: b = a;
316: a = temp;
317: }
318:
319: // Round 2
320: for (int i = 20; i < 40; i++) {
321: temp = ((a << 5) | (a >>> (32 - 5))) + (b ^ c ^ d) + e
322: + W[i] + round2_kt;
323: e = d;
324: d = c;
325: c = ((b << 30) | (b >>> (32 - 30)));
326: b = a;
327: a = temp;
328: }
329:
330: // Round 3
331: for (int i = 40; i < 60; i++) {
332: temp = ((a << 5) | (a >>> (32 - 5)))
333: + ((b & c) | (b & d) | (c & d)) + e + W[i]
334: + round3_kt;
335: e = d;
336: d = c;
337: c = ((b << 30) | (b >>> (32 - 30)));
338: b = a;
339: a = temp;
340: }
341:
342: // Round 4
343: for (int i = 60; i < 80; i++) {
344: temp = ((a << 5) | (a >>> (32 - 5))) + (b ^ c ^ d) + e
345: + W[i] + round4_kt;
346: e = d;
347: d = c;
348: c = ((b << 30) | (b >>> (32 - 30)));
349: b = a;
350: a = temp;
351: }
352: AA += a;
353: BB += b;
354: CC += c;
355: DD += d;
356: EE += e;
357: }
358:
359: /*
360: * Clones this object.
361: */
362: public Object clone() {
363: SHA that = null;
364: try {
365: that = (SHA) super .clone();
366: that.W = new int[80];
367: System.arraycopy(this .W, 0, that.W, 0, W.length);
368: return that;
369: } catch (CloneNotSupportedException e) {
370: }
371: return that;
372: }
373: }
|