001: /*
002: * @(#)SHA5.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-512 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 SHA5 extends MessageDigestSpi implements Cloneable {
046:
047: private static final int LENGTH = 64;
048: private static final long[] INITIAL_HASHES = { 0x6a09e667f3bcc908L,
049: 0xbb67ae8584caa73bL, 0x3c6ef372fe94f82bL,
050: 0xa54ff53a5f1d36f1L, 0x510e527fade682d1L,
051: 0x9b05688c2b3e6c1fL, 0x1f83d9abfb41bd6bL,
052: 0x5be0cd19137e2179L };
053: private static final int ITERATION = 80;
054: // Constants for each round/iteration
055: private static final long[] ROUND_CONSTS = { 0x428A2F98D728AE22L,
056: 0x7137449123EF65CDL, 0xB5C0FBCFEC4D3B2FL,
057: 0xE9B5DBA58189DBBCL, 0x3956C25BF348B538L,
058: 0x59F111F1B605D019L, 0x923F82A4AF194F9BL,
059: 0xAB1C5ED5DA6D8118L, 0xD807AA98A3030242L,
060: 0x12835B0145706FBEL, 0x243185BE4EE4B28CL,
061: 0x550C7DC3D5FFB4E2L, 0x72BE5D74F27B896FL,
062: 0x80DEB1FE3B1696B1L, 0x9BDC06A725C71235L,
063: 0xC19BF174CF692694L, 0xE49B69C19EF14AD2L,
064: 0xEFBE4786384F25E3L, 0x0FC19DC68B8CD5B5L,
065: 0x240CA1CC77AC9C65L, 0x2DE92C6F592B0275L,
066: 0x4A7484AA6EA6E483L, 0x5CB0A9DCBD41FBD4L,
067: 0x76F988DA831153B5L, 0x983E5152EE66DFABL,
068: 0xA831C66D2DB43210L, 0xB00327C898FB213FL,
069: 0xBF597FC7BEEF0EE4L, 0xC6E00BF33DA88FC2L,
070: 0xD5A79147930AA725L, 0x06CA6351E003826FL,
071: 0x142929670A0E6E70L, 0x27B70A8546D22FFCL,
072: 0x2E1B21385C26C926L, 0x4D2C6DFC5AC42AEDL,
073: 0x53380D139D95B3DFL, 0x650A73548BAF63DEL,
074: 0x766A0ABB3C77B2A8L, 0x81C2C92E47EDAEE6L,
075: 0x92722C851482353BL, 0xA2BFE8A14CF10364L,
076: 0xA81A664BBC423001L, 0xC24B8B70D0F89791L,
077: 0xC76C51A30654BE30L, 0xD192E819D6EF5218L,
078: 0xD69906245565A910L, 0xF40E35855771202AL,
079: 0x106AA07032BBD1B8L, 0x19A4C116B8D2D0C8L,
080: 0x1E376C085141AB53L, 0x2748774CDF8EEB99L,
081: 0x34B0BCB5E19B48A8L, 0x391C0CB3C5C95A63L,
082: 0x4ED8AA4AE3418ACBL, 0x5B9CCA4F7763E373L,
083: 0x682E6FF3D6B2B8A3L, 0x748F82EE5DEFB2FCL,
084: 0x78A5636F43172F60L, 0x84C87814A1F0AB72L,
085: 0x8CC702081A6439ECL, 0x90BEFFFA23631E28L,
086: 0xA4506CEBDE82BDE9L, 0xBEF9A3F7B2C67915L,
087: 0xC67178F2E372532BL, 0xCA273ECEEA26619CL,
088: 0xD186B8C721C0C207L, 0xEADA7DD6CDE0EB1EL,
089: 0xF57D4F7FEE6ED178L, 0x06F067AA72176FBAL,
090: 0x0A637DC5A2C898A6L, 0x113F9804BEF90DAEL,
091: 0x1B710B35131C471BL, 0x28DB77F523047D84L,
092: 0x32CAAB7B40C72493L, 0x3C9EBE0A15C9BEBCL,
093: 0x431D67C49C100D4CL, 0x4CC5D4BECB3E42B6L,
094: 0x597F299CFC657E2AL, 0x5FCB6FAB3AD6FAECL,
095: 0x6C44198C4A475817L };
096:
097: private final long COUNT_MASK = 127; // block size - 1
098: private long W[] = new long[ITERATION];
099: private long count = 0;
100:
101: private long AA, BB, CC, DD, EE, FF, GG, HH;
102:
103: /**
104: * logical function ch(x,y,z) as defined in spec:
105: * @return (x and y) xor ((complement x) and z)
106: * @param x long
107: * @param y long
108: * @param z long
109: */
110: private static long lf_ch(long x, long y, long z) {
111: return (x & y) ^ ((~x) & z);
112: }
113:
114: /**
115: * logical function maj(x,y,z) as defined in spec:
116: * @return (x and y) xor (x and z) xor (y and z)
117: * @param x long
118: * @param y long
119: * @param z long
120: */
121: private static long lf_maj(long x, long y, long z) {
122: return (x & y) ^ (x & z) ^ (y & z);
123: }
124:
125: /**
126: * logical function R(x,s) - right shift
127: * @return x right shift for s times
128: * @param x long
129: * @param s int
130: */
131: private static long lf_R(long x, int s) {
132: return (x >>> s);
133: }
134:
135: /**
136: * logical function S(x,s) - right rotation
137: * @return x circular right shift for s times
138: * @param x long
139: * @param s int
140: */
141: private static long lf_S(long x, int s) {
142: return (x >>> s) | (x << (64 - s));
143: }
144:
145: /**
146: * logical function sigma0(x) - xor of results of right rotations
147: * @return S(x,28) xor S(x,34) xor S(x,39)
148: * @param x long
149: */
150: private static long lf_sigma0(long x) {
151: return lf_S(x, 28) ^ lf_S(x, 34) ^ lf_S(x, 39);
152: }
153:
154: /**
155: * logical function sigma1(x) - xor of results of right rotations
156: * @return S(x,14) xor S(x,18) xor S(x,41)
157: * @param x long
158: */
159: private static long lf_sigma1(long x) {
160: return lf_S(x, 14) ^ lf_S(x, 18) ^ lf_S(x, 41);
161: }
162:
163: /**
164: * logical function delta0(x) - xor of results of right shifts/rotations
165: * @return long
166: * @param x long
167: */
168: private static long lf_delta0(long x) {
169: return lf_S(x, 1) ^ lf_S(x, 8) ^ lf_R(x, 7);
170: }
171:
172: /**
173: * logical function delta1(x) - xor of results of right shifts/rotations
174: * @return long
175: * @param x long
176: */
177: private static long lf_delta1(long x) {
178: return lf_S(x, 19) ^ lf_S(x, 61) ^ lf_R(x, 6);
179: }
180:
181: /**
182: * Creates a SHA5 object with state (for cloning)
183: */
184: SHA5(SHA5 sha) {
185: this ();
186: System.arraycopy(sha.W, 0, this .W, 0, W.length);
187: this .count = sha.count;
188: this .AA = sha.AA;
189: this .BB = sha.BB;
190: this .CC = sha.CC;
191: this .DD = sha.DD;
192: this .EE = sha.EE;
193: this .FF = sha.FF;
194: this .GG = sha.GG;
195: this .HH = sha.HH;
196: }
197:
198: /**
199: * Creates a new SHA object.
200: */
201: public SHA5() {
202: init();
203: }
204:
205: /**
206: * @return the length of the digest in bytes
207: */
208: protected int engineGetDigestLength() {
209: return (LENGTH);
210: }
211:
212: /**
213: * Update a byte.
214: *
215: * @param b the byte
216: */
217: protected void engineUpdate(byte b) {
218: update((int) b);
219: }
220:
221: private void update(int b) {
222: int word; // index inside this block, i.e. from 0 to 15.
223: int offset; //offset of this byte inside the word
224:
225: /* compute word index within the block and bit offset within the word.
226: block size is 128 bytes with word size is 8 bytes. offset is in
227: terms of bits */
228: word = (int) (count & COUNT_MASK) >>> 3;
229: offset = (int) (~count & 7) << 3;
230:
231: // clear the byte inside W[word] and then 'or' it with b's byte value
232: W[word] = (W[word] & ~(0xffL << offset))
233: | ((b & 0xffL) << offset);
234: count++;
235:
236: /* If this is the last byte of a block, compute the partial hash */
237: if ((count & COUNT_MASK) == 0) {
238: computeBlock();
239: }
240: }
241:
242: /**
243: * Update a buffer.
244: *
245: * @param b the data to be updated.
246: * @param off the start offset in the data
247: * @param len the number of bytes to be updated.
248: */
249: protected void engineUpdate(byte b[], int off, int len) {
250: int word;
251: int offset;
252:
253: if ((off < 0) || (len < 0) || (off + len > b.length))
254: throw new ArrayIndexOutOfBoundsException();
255:
256: // Use single writes until integer aligned
257: while ((len > 0) && (count & 7) != 0) {
258: engineUpdate(b[off]);
259: off++;
260: len--;
261: }
262:
263: /* Assemble groups of 8 bytes to be inserted in long array */
264: while (len >= 8) {
265:
266: word = (int) (count & COUNT_MASK) >> 3;
267: W[word] = ((b[off] & 0xffL) << 56)
268: | ((b[off + 1] & 0xffL) << 48)
269: | ((b[off + 2] & 0xffL) << 40)
270: | ((b[off + 3] & 0xffL) << 32)
271: | ((b[off + 4] & 0xffL) << 24)
272: | ((b[off + 5] & 0xffL) << 16)
273: | ((b[off + 6] & 0xffL) << 8)
274: | ((b[off + 7] & 0xffL));
275: count += 8;
276: if ((count & COUNT_MASK) == 0) {
277: computeBlock();
278: }
279: len -= 8;
280: off += 8;
281: }
282:
283: /* Use single writes for last few bytes */
284: while (len > 0) {
285: engineUpdate(b[off++]);
286: len--;
287: }
288: }
289:
290: /**
291: * Resets the buffers and hash value to start a new hash.
292: */
293: void init() {
294: setInitialHash(INITIAL_HASHES);
295: for (int i = 0; i < ITERATION; i++)
296: W[i] = 0;
297: count = 0;
298: }
299:
300: void setInitialHash(long[] values) {
301: AA = values[0];
302: BB = values[1];
303: CC = values[2];
304: DD = values[3];
305: EE = values[4];
306: FF = values[5];
307: GG = values[6];
308: HH = values[7];
309: }
310:
311: /**
312: * Resets the buffers and hash value to start a new hash.
313: */
314: protected void engineReset() {
315: init();
316: }
317:
318: /**
319: * Computes the final hash and returns the final value as a
320: * byte array. The object is reset to be ready for further
321: * use, as specified in java.security.MessageDigest javadoc
322: * specification.
323: */
324: protected byte[] engineDigest() {
325: byte hashvalue[] = new byte[LENGTH];
326:
327: try {
328: int outLen = engineDigest(hashvalue, 0, hashvalue.length);
329: } catch (DigestException e) {
330: throw new InternalError("");
331: }
332: return hashvalue;
333: }
334:
335: /**
336: * Computes the final hash and places the final value in the
337: * specified array. The object is reset to be ready for further
338: * use, as specified in java.security.MessageDigest javadoc
339: * specification.
340: * @param hashvalue buffer to hold the digest
341: * @param offset offset for storing the digest
342: * @param len length of the buffer
343: * @return length of the digest in bytes
344: */
345: protected int engineDigest(byte[] hashvalue, int offset, int len)
346: throws DigestException {
347:
348: if (len < LENGTH) {
349: throw new DigestException("partial digests not returned");
350: }
351: if (hashvalue.length - offset < LENGTH) {
352: throw new DigestException("output buffer too small "
353: + "to store the digest");
354: }
355: performDigest(hashvalue, offset, LENGTH);
356: return LENGTH;
357: }
358:
359: void performDigest(byte[] hashvalue, int offset, int resultLength)
360: throws DigestException {
361: /* The input length in bits before padding occurs */
362: long inputLength = count << 3;
363:
364: update(0x80);
365:
366: /* Pad with zeros until overall length is a multiple of 896 */
367: while ((int) (count & COUNT_MASK) != 112) {
368: update(0);
369: }
370:
371: W[14] = 0;
372: W[15] = inputLength;
373: count += 16;
374: computeBlock();
375:
376: // Copy out the result
377: switch (resultLength) {
378: case 64:
379: hashvalue[offset + 63] = (byte) (HH >>> 0);
380: hashvalue[offset + 62] = (byte) (HH >>> 8);
381: hashvalue[offset + 61] = (byte) (HH >>> 16);
382: hashvalue[offset + 60] = (byte) (HH >>> 24);
383: hashvalue[offset + 59] = (byte) (HH >>> 32);
384: hashvalue[offset + 58] = (byte) (HH >>> 40);
385: hashvalue[offset + 57] = (byte) (HH >>> 48);
386: hashvalue[offset + 56] = (byte) (HH >>> 56);
387: hashvalue[offset + 55] = (byte) (GG >>> 0);
388: hashvalue[offset + 54] = (byte) (GG >>> 8);
389: hashvalue[offset + 53] = (byte) (GG >>> 16);
390: hashvalue[offset + 52] = (byte) (GG >>> 24);
391: hashvalue[offset + 51] = (byte) (GG >>> 32);
392: hashvalue[offset + 50] = (byte) (GG >>> 40);
393: hashvalue[offset + 49] = (byte) (GG >>> 48);
394: hashvalue[offset + 48] = (byte) (GG >>> 56);
395: case 48:
396: hashvalue[offset + 47] = (byte) (FF >>> 0);
397: hashvalue[offset + 46] = (byte) (FF >>> 8);
398: hashvalue[offset + 45] = (byte) (FF >>> 16);
399: hashvalue[offset + 44] = (byte) (FF >>> 24);
400: hashvalue[offset + 43] = (byte) (FF >>> 32);
401: hashvalue[offset + 42] = (byte) (FF >>> 40);
402: hashvalue[offset + 41] = (byte) (FF >>> 48);
403: hashvalue[offset + 40] = (byte) (FF >>> 56);
404: hashvalue[offset + 39] = (byte) (EE >>> 0);
405: hashvalue[offset + 38] = (byte) (EE >>> 8);
406: hashvalue[offset + 37] = (byte) (EE >>> 16);
407: hashvalue[offset + 36] = (byte) (EE >>> 24);
408: hashvalue[offset + 35] = (byte) (EE >>> 32);
409: hashvalue[offset + 34] = (byte) (EE >>> 40);
410: hashvalue[offset + 33] = (byte) (EE >>> 48);
411: hashvalue[offset + 32] = (byte) (EE >>> 56);
412: hashvalue[offset + 31] = (byte) (DD >>> 0);
413: hashvalue[offset + 30] = (byte) (DD >>> 8);
414: hashvalue[offset + 29] = (byte) (DD >>> 16);
415: hashvalue[offset + 28] = (byte) (DD >>> 24);
416: hashvalue[offset + 27] = (byte) (DD >>> 32);
417: hashvalue[offset + 26] = (byte) (DD >>> 40);
418: hashvalue[offset + 25] = (byte) (DD >>> 48);
419: hashvalue[offset + 24] = (byte) (DD >>> 56);
420: hashvalue[offset + 23] = (byte) (CC >>> 0);
421: hashvalue[offset + 22] = (byte) (CC >>> 8);
422: hashvalue[offset + 21] = (byte) (CC >>> 16);
423: hashvalue[offset + 20] = (byte) (CC >>> 24);
424: hashvalue[offset + 19] = (byte) (CC >>> 32);
425: hashvalue[offset + 18] = (byte) (CC >>> 40);
426: hashvalue[offset + 17] = (byte) (CC >>> 48);
427: hashvalue[offset + 16] = (byte) (CC >>> 56);
428: hashvalue[offset + 15] = (byte) (BB >>> 0);
429: hashvalue[offset + 14] = (byte) (BB >>> 8);
430: hashvalue[offset + 13] = (byte) (BB >>> 16);
431: hashvalue[offset + 12] = (byte) (BB >>> 24);
432: hashvalue[offset + 11] = (byte) (BB >>> 32);
433: hashvalue[offset + 10] = (byte) (BB >>> 40);
434: hashvalue[offset + 9] = (byte) (BB >>> 48);
435: hashvalue[offset + 8] = (byte) (BB >>> 56);
436: hashvalue[offset + 7] = (byte) (AA >>> 0);
437: hashvalue[offset + 6] = (byte) (AA >>> 8);
438: hashvalue[offset + 5] = (byte) (AA >>> 16);
439: hashvalue[offset + 4] = (byte) (AA >>> 24);
440: hashvalue[offset + 3] = (byte) (AA >>> 32);
441: hashvalue[offset + 2] = (byte) (AA >>> 40);
442: hashvalue[offset + 1] = (byte) (AA >>> 48);
443: hashvalue[offset + 0] = (byte) (AA >>> 56);
444: break;
445: default:
446: throw new DigestException("Unsupported Digest Length!");
447: }
448: engineReset();
449: }
450:
451: /**
452: * Compute the hash for the current block.
453: *
454: * This is in the same vein as Peter Gutmann's algorithm listed in
455: * the back of Applied Cryptography, Compact implementation of
456: * "old" NIST Secure Hash Algorithm.
457: *
458: */
459: private void computeBlock() {
460: long T1, T2, a, b, c, d, e, f, g, h;
461:
462: // The first 16 longs are from the byte stream, compute the rest of
463: // the W[]'s
464: for (int t = 16; t < ITERATION; t++) {
465: W[t] = lf_delta1(W[t - 2]) + W[t - 7]
466: + lf_delta0(W[t - 15]) + W[t - 16];
467: }
468:
469: a = AA;
470: b = BB;
471: c = CC;
472: d = DD;
473: e = EE;
474: f = FF;
475: g = GG;
476: h = HH;
477:
478: for (int i = 0; i < ITERATION; i++) {
479: T1 = h + lf_sigma1(e) + lf_ch(e, f, g) + ROUND_CONSTS[i]
480: + W[i];
481: T2 = lf_sigma0(a) + lf_maj(a, b, c);
482: h = g;
483: g = f;
484: f = e;
485: e = d + T1;
486: d = c;
487: c = b;
488: b = a;
489: a = T1 + T2;
490: }
491: AA += a;
492: BB += b;
493: CC += c;
494: DD += d;
495: EE += e;
496: FF += f;
497: GG += g;
498: HH += h;
499: }
500:
501: /*
502: * Clones this object.
503: */
504: public Object clone() {
505: SHA5 that = null;
506: that = new SHA5(this);
507: return that;
508: }
509: }
|