001: /*
002: * @(#)SHA2.java 1.6 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: package sun.security.provider;
028:
029: import java.security.*;
030: import java.math.BigInteger;
031:
032: /**
033: * This class implements the Secure Hash Algorithm SHA-256 developed by
034: * the National Institute of Standards and Technology along with the
035: * National Security Agency.
036: *
037: * <p>It implements java.security.MessageDigestSpi, and can be used
038: * through Java Cryptography Architecture (JCA), as a pluggable
039: * MessageDigest implementation.
040: *
041: * @version 1.6 10/10/06
042: * @author Valerie Peng
043: */
044:
045: public class SHA2 extends MessageDigestSpi implements Cloneable {
046:
047: private static final int LENGTH = 32;
048: private static final int ITERATION = 64;
049: private static final int COUNT_MASK = 63; // block size - 1
050: // Constants for each round
051: private static final int[] ROUND_CONSTS = { 0x428a2f98, 0x71374491,
052: 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4,
053: 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
054: 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1,
055: 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa,
056: 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8,
057: 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
058: 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354,
059: 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
060: 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585,
061: 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
062: 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee,
063: 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb,
064: 0xbef9a3f7, 0xc67178f2 };
065:
066: private int W[] = new int[ITERATION];
067: private long count = 0;
068: private int AA, BB, CC, DD, EE, FF, GG, HH;
069:
070: /**
071: * logical function ch(x,y,z) as defined in spec:
072: * @return (x and y) xor ((complement x) and z)
073: * @param x int
074: * @param y int
075: * @param z int
076: */
077: private static int lf_ch(int x, int y, int z) {
078: return (x & y) ^ ((~x) & z);
079: }
080:
081: /**
082: * logical function maj(x,y,z) as defined in spec:
083: * @return (x and y) xor (x and z) xor (y and z)
084: * @param x int
085: * @param y int
086: * @param z int
087: */
088: private static int lf_maj(int x, int y, int z) {
089: return (x & y) ^ (x & z) ^ (y & z);
090: }
091:
092: /**
093: * logical function R(x,s) - right shift
094: * @return x right shift for s times
095: * @param x int
096: * @param s int
097: */
098: private static int lf_R(int x, int s) {
099: return (x >>> s);
100: }
101:
102: /**
103: * logical function S(x,s) - right rotation
104: * @return x circular right shift for s times
105: * @param x int
106: * @param s int
107: */
108: private static int lf_S(int x, int s) {
109: return (x >>> s) | (x << (32 - s));
110: }
111:
112: /**
113: * logical function sigma0(x) - xor of results of right rotations
114: * @return S(x,2) xor S(x,13) xor S(x,22)
115: * @param x int
116: */
117: private static int lf_sigma0(int x) {
118: return lf_S(x, 2) ^ lf_S(x, 13) ^ lf_S(x, 22);
119: }
120:
121: /**
122: * logical function sigma1(x) - xor of results of right rotations
123: * @return S(x,6) xor S(x,11) xor S(x,25)
124: * @param x int
125: */
126: private static int lf_sigma1(int x) {
127: return lf_S(x, 6) ^ lf_S(x, 11) ^ lf_S(x, 25);
128: }
129:
130: /**
131: * logical function delta0(x) - xor of results of right shifts/rotations
132: * @return int
133: * @param x int
134: */
135: private static int lf_delta0(int x) {
136: return lf_S(x, 7) ^ lf_S(x, 18) ^ lf_R(x, 3);
137: }
138:
139: /**
140: * logical function delta1(x) - xor of results of right shifts/rotations
141: * @return int
142: * @param x int
143: */
144: private static int lf_delta1(int x) {
145: return lf_S(x, 17) ^ lf_S(x, 19) ^ lf_R(x, 10);
146: }
147:
148: /**
149: * Creates a SHA2 object.with state (for cloning)
150: */
151: private SHA2(SHA2 sha) {
152: this ();
153: System.arraycopy(sha.W, 0, this .W, 0, W.length);
154: this .count = sha.count;
155: this .AA = sha.AA;
156: this .BB = sha.BB;
157: this .CC = sha.CC;
158: this .DD = sha.DD;
159: this .EE = sha.EE;
160: this .FF = sha.FF;
161: this .GG = sha.GG;
162: this .HH = sha.HH;
163: }
164:
165: /**
166: * Creates a new SHA object.
167: */
168: public SHA2() {
169: init();
170: }
171:
172: /**
173: * @return the length of the digest in bytes
174: */
175: protected int engineGetDigestLength() {
176: return (LENGTH);
177: }
178:
179: /**
180: * Update a byte.
181: *
182: * @param b the byte
183: */
184: protected void engineUpdate(byte b) {
185: update((int) b);
186: }
187:
188: private void update(int b) {
189: int word; // index inside this block, i.e. from 0 to 15.
190: int offset; // offset of this byte inside the word
191:
192: /* compute word index within the block and bit offset within the word.
193: block size is 64 bytes with word size is 4 bytes. offset is in
194: terms of bits */
195: word = ((int) count & COUNT_MASK) >>> 2;
196: offset = (~(int) count & 3) << 3;
197:
198: // clear the byte inside W[word] and then 'or' it with b's byte value
199: W[word] = (W[word] & ~(0xff << offset))
200: | ((b & 0xff) << offset);
201:
202: /* If this is the last byte of a block, compute the partial hash */
203: if (((int) count & COUNT_MASK) == COUNT_MASK) {
204: computeBlock();
205: }
206: count++;
207: }
208:
209: /**
210: * Update a buffer.
211: *
212: * @param b the data to be updated.
213: * @param off the start offset in the data
214: * @param len the number of bytes to be updated.
215: */
216: protected void engineUpdate(byte b[], int off, int len) {
217: int word;
218: int offset;
219:
220: if ((off < 0) || (len < 0) || (off + len > b.length))
221: throw new ArrayIndexOutOfBoundsException();
222:
223: // Use single writes until integer aligned
224: while ((len > 0) && ((int) count & 3) != 0) {
225: engineUpdate(b[off]);
226: off++;
227: len--;
228: }
229:
230: /* Assemble groups of 4 bytes to be inserted in integer array */
231: while (len >= 4) {
232:
233: word = ((int) count & COUNT_MASK) >> 2;
234:
235: W[word] = ((b[off] & 0xff) << 24)
236: | ((b[off + 1] & 0xff) << 16)
237: | ((b[off + 2] & 0xff) << 8)
238: | ((b[off + 3] & 0xff));
239:
240: count += 4;
241: if (((int) count & COUNT_MASK) == 0) {
242: computeBlock();
243: }
244: len -= 4;
245: off += 4;
246: }
247:
248: /* Use single writes for last few bytes */
249: while (len > 0) {
250: engineUpdate(b[off++]);
251: len--;
252: }
253: }
254:
255: /**
256: * Resets the buffers and hash value to start a new hash.
257: */
258: private void init() {
259: AA = 0x6a09e667;
260: BB = 0xbb67ae85;
261: CC = 0x3c6ef372;
262: DD = 0xa54ff53a;
263: EE = 0x510e527f;
264: FF = 0x9b05688c;
265: GG = 0x1f83d9ab;
266: HH = 0x5be0cd19;
267: for (int i = 0; i < ITERATION; i++)
268: W[i] = 0;
269: count = 0;
270: }
271:
272: /**
273: * Resets the buffers and hash value to start a new hash.
274: */
275: protected void engineReset() {
276: init();
277: }
278:
279: /**
280: * Computes the final hash and returns the final value as a
281: * byte[32] array. The object is reset to be ready for further
282: * use, as specified in the JavaSecurity MessageDigest
283: * specification.
284: * @return the digest
285: */
286: protected byte[] engineDigest() {
287: byte hashvalue[] = new byte[LENGTH];
288:
289: try {
290: int outLen = engineDigest(hashvalue, 0, hashvalue.length);
291: } catch (DigestException e) {
292: throw new InternalError("");
293: }
294: return hashvalue;
295: }
296:
297: /**
298: * Computes the final hash and places the final value in the
299: * specified array. The object is reset to be ready for further
300: * use, as specified in java.security.MessageDigest javadoc
301: * specification.
302: * @param hashvalue buffer to hold the digest
303: * @param offset offset for storing the digest
304: * @param len length of the buffer
305: * @return length of the digest in bytes
306: */
307: protected int engineDigest(byte[] hashvalue, int offset, int len)
308: throws DigestException {
309:
310: if (len < LENGTH) {
311: throw new DigestException("partial digests not returned");
312: }
313: if (hashvalue.length - offset < LENGTH) {
314: throw new DigestException(
315: "insufficient space in the output "
316: + "buffer to store the digest");
317: }
318: /* The input length in bits before padding occurs */
319: long inputLength = count << 3;
320:
321: update(0x80);
322:
323: /* Pad with zeros until overall length is a multiple of 448 */
324: while ((int) (count & COUNT_MASK) != 56) {
325: update(0);
326: }
327:
328: W[14] = (int) (inputLength >>> 32);
329: W[15] = (int) (inputLength & 0xffffffff);
330:
331: count += 8;
332: computeBlock();
333:
334: // Copy out the result
335: hashvalue[offset + 0] = (byte) (AA >>> 24);
336: hashvalue[offset + 1] = (byte) (AA >>> 16);
337: hashvalue[offset + 2] = (byte) (AA >>> 8);
338: hashvalue[offset + 3] = (byte) (AA >>> 0);
339:
340: hashvalue[offset + 4] = (byte) (BB >>> 24);
341: hashvalue[offset + 5] = (byte) (BB >>> 16);
342: hashvalue[offset + 6] = (byte) (BB >>> 8);
343: hashvalue[offset + 7] = (byte) (BB >>> 0);
344:
345: hashvalue[offset + 8] = (byte) (CC >>> 24);
346: hashvalue[offset + 9] = (byte) (CC >>> 16);
347: hashvalue[offset + 10] = (byte) (CC >>> 8);
348: hashvalue[offset + 11] = (byte) (CC >>> 0);
349:
350: hashvalue[offset + 12] = (byte) (DD >>> 24);
351: hashvalue[offset + 13] = (byte) (DD >>> 16);
352: hashvalue[offset + 14] = (byte) (DD >>> 8);
353: hashvalue[offset + 15] = (byte) (DD >>> 0);
354:
355: hashvalue[offset + 16] = (byte) (EE >>> 24);
356: hashvalue[offset + 17] = (byte) (EE >>> 16);
357: hashvalue[offset + 18] = (byte) (EE >>> 8);
358: hashvalue[offset + 19] = (byte) (EE >>> 0);
359:
360: hashvalue[offset + 20] = (byte) (FF >>> 24);
361: hashvalue[offset + 21] = (byte) (FF >>> 16);
362: hashvalue[offset + 22] = (byte) (FF >>> 8);
363: hashvalue[offset + 23] = (byte) (FF >>> 0);
364:
365: hashvalue[offset + 24] = (byte) (GG >>> 24);
366: hashvalue[offset + 25] = (byte) (GG >>> 16);
367: hashvalue[offset + 26] = (byte) (GG >>> 8);
368: hashvalue[offset + 27] = (byte) (GG >>> 0);
369:
370: hashvalue[offset + 28] = (byte) (HH >>> 24);
371: hashvalue[offset + 29] = (byte) (HH >>> 16);
372: hashvalue[offset + 30] = (byte) (HH >>> 8);
373: hashvalue[offset + 31] = (byte) (HH >>> 0);
374:
375: engineReset(); // remove the evidence
376:
377: return LENGTH;
378: }
379:
380: /**
381: * Compute the hash for the current block and stores the results
382: * in internal variable AA, BB, CC, DD, EE, FF, GG, HH
383: */
384: private void computeBlock() {
385: int T1, T2, a, b, c, d, e, f, g, h;
386:
387: // The first 16 ints are from the byte stream, compute the rest of
388: // the W[]'s
389: for (int t = 16; t < ITERATION; t++) {
390: W[t] = lf_delta1(W[t - 2]) + W[t - 7]
391: + lf_delta0(W[t - 15]) + W[t - 16];
392: }
393:
394: a = AA;
395: b = BB;
396: c = CC;
397: d = DD;
398: e = EE;
399: f = FF;
400: g = GG;
401: h = HH;
402:
403: for (int i = 0; i < ITERATION; i++) {
404: T1 = h + lf_sigma1(e) + lf_ch(e, f, g) + ROUND_CONSTS[i]
405: + W[i];
406: T2 = lf_sigma0(a) + lf_maj(a, b, c);
407: h = g;
408: g = f;
409: f = e;
410: e = d + T1;
411: d = c;
412: c = b;
413: b = a;
414: a = T1 + T2;
415: }
416: AA += a;
417: BB += b;
418: CC += c;
419: DD += d;
420: EE += e;
421: FF += f;
422: GG += g;
423: HH += h;
424: }
425:
426: /*
427: * Clones this object.
428: */
429: public Object clone() {
430: SHA2 that = null;
431: that = (SHA2) new SHA2(this);
432: return that;
433: }
434: }
|