001: package org.bouncycastle.crypto.digests;
002:
003: import org.bouncycastle.crypto.ExtendedDigest;
004:
005: /**
006: * Base class for SHA-384 and SHA-512.
007: */
008: public abstract class LongDigest implements ExtendedDigest {
009: private static final int BYTE_LENGTH = 128;
010:
011: private byte[] xBuf;
012: private int xBufOff;
013:
014: private long byteCount1;
015: private long byteCount2;
016:
017: protected long H1, H2, H3, H4, H5, H6, H7, H8;
018:
019: private long[] W = new long[80];
020: private int wOff;
021:
022: /**
023: * Constructor for variable length word
024: */
025: protected LongDigest() {
026: xBuf = new byte[8];
027: xBufOff = 0;
028:
029: reset();
030: }
031:
032: /**
033: * Copy constructor. We are using copy constructors in place
034: * of the Object.clone() interface as this interface is not
035: * supported by J2ME.
036: */
037: protected LongDigest(LongDigest t) {
038: xBuf = new byte[t.xBuf.length];
039: System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length);
040:
041: xBufOff = t.xBufOff;
042: byteCount1 = t.byteCount1;
043: byteCount2 = t.byteCount2;
044:
045: H1 = t.H1;
046: H2 = t.H2;
047: H3 = t.H3;
048: H4 = t.H4;
049: H5 = t.H5;
050: H6 = t.H6;
051: H7 = t.H7;
052: H8 = t.H8;
053:
054: System.arraycopy(t.W, 0, W, 0, t.W.length);
055: wOff = t.wOff;
056: }
057:
058: public void update(byte in) {
059: xBuf[xBufOff++] = in;
060:
061: if (xBufOff == xBuf.length) {
062: processWord(xBuf, 0);
063: xBufOff = 0;
064: }
065:
066: byteCount1++;
067: }
068:
069: public void update(byte[] in, int inOff, int len) {
070: //
071: // fill the current word
072: //
073: while ((xBufOff != 0) && (len > 0)) {
074: update(in[inOff]);
075:
076: inOff++;
077: len--;
078: }
079:
080: //
081: // process whole words.
082: //
083: while (len > xBuf.length) {
084: processWord(in, inOff);
085:
086: inOff += xBuf.length;
087: len -= xBuf.length;
088: byteCount1 += xBuf.length;
089: }
090:
091: //
092: // load in the remainder.
093: //
094: while (len > 0) {
095: update(in[inOff]);
096:
097: inOff++;
098: len--;
099: }
100: }
101:
102: public void finish() {
103: adjustByteCounts();
104:
105: long lowBitLength = byteCount1 << 3;
106: long hiBitLength = byteCount2;
107:
108: //
109: // add the pad bytes.
110: //
111: update((byte) 128);
112:
113: while (xBufOff != 0) {
114: update((byte) 0);
115: }
116:
117: processLength(lowBitLength, hiBitLength);
118:
119: processBlock();
120: }
121:
122: public void reset() {
123: byteCount1 = 0;
124: byteCount2 = 0;
125:
126: xBufOff = 0;
127: for (int i = 0; i < xBuf.length; i++) {
128: xBuf[i] = 0;
129: }
130:
131: wOff = 0;
132: for (int i = 0; i != W.length; i++) {
133: W[i] = 0;
134: }
135: }
136:
137: public int getByteLength() {
138: return BYTE_LENGTH;
139: }
140:
141: protected void processWord(byte[] in, int inOff) {
142: W[wOff++] = ((long) (in[inOff] & 0xff) << 56)
143: | ((long) (in[inOff + 1] & 0xff) << 48)
144: | ((long) (in[inOff + 2] & 0xff) << 40)
145: | ((long) (in[inOff + 3] & 0xff) << 32)
146: | ((long) (in[inOff + 4] & 0xff) << 24)
147: | ((long) (in[inOff + 5] & 0xff) << 16)
148: | ((long) (in[inOff + 6] & 0xff) << 8)
149: | ((in[inOff + 7] & 0xff));
150:
151: if (wOff == 16) {
152: processBlock();
153: }
154: }
155:
156: protected void unpackWord(long word, byte[] out, int outOff) {
157: out[outOff] = (byte) (word >>> 56);
158: out[outOff + 1] = (byte) (word >>> 48);
159: out[outOff + 2] = (byte) (word >>> 40);
160: out[outOff + 3] = (byte) (word >>> 32);
161: out[outOff + 4] = (byte) (word >>> 24);
162: out[outOff + 5] = (byte) (word >>> 16);
163: out[outOff + 6] = (byte) (word >>> 8);
164: out[outOff + 7] = (byte) word;
165: }
166:
167: /**
168: * adjust the byte counts so that byteCount2 represents the
169: * upper long (less 3 bits) word of the byte count.
170: */
171: private void adjustByteCounts() {
172: if (byteCount1 > 0x1fffffffffffffffL) {
173: byteCount2 += (byteCount1 >>> 61);
174: byteCount1 &= 0x1fffffffffffffffL;
175: }
176: }
177:
178: protected void processLength(long lowW, long hiW) {
179: if (wOff > 14) {
180: processBlock();
181: }
182:
183: W[14] = hiW;
184: W[15] = lowW;
185: }
186:
187: protected void processBlock() {
188: adjustByteCounts();
189:
190: //
191: // expand 16 word block into 80 word blocks.
192: //
193: for (int t = 16; t <= 79; t++) {
194: W[t] = Sigma1(W[t - 2]) + W[t - 7] + Sigma0(W[t - 15])
195: + W[t - 16];
196: }
197:
198: //
199: // set up working variables.
200: //
201: long a = H1;
202: long b = H2;
203: long c = H3;
204: long d = H4;
205: long e = H5;
206: long f = H6;
207: long g = H7;
208: long h = H8;
209:
210: int t = 0;
211: for (int i = 0; i < 10; i++) {
212: // t = 8 * i
213: h += Sum1(e) + Ch(e, f, g) + K[t] + W[t++];
214: d += h;
215: h += Sum0(a) + Maj(a, b, c);
216:
217: // t = 8 * i + 1
218: g += Sum1(d) + Ch(d, e, f) + K[t] + W[t++];
219: c += g;
220: g += Sum0(h) + Maj(h, a, b);
221:
222: // t = 8 * i + 2
223: f += Sum1(c) + Ch(c, d, e) + K[t] + W[t++];
224: b += f;
225: f += Sum0(g) + Maj(g, h, a);
226:
227: // t = 8 * i + 3
228: e += Sum1(b) + Ch(b, c, d) + K[t] + W[t++];
229: a += e;
230: e += Sum0(f) + Maj(f, g, h);
231:
232: // t = 8 * i + 4
233: d += Sum1(a) + Ch(a, b, c) + K[t] + W[t++];
234: h += d;
235: d += Sum0(e) + Maj(e, f, g);
236:
237: // t = 8 * i + 5
238: c += Sum1(h) + Ch(h, a, b) + K[t] + W[t++];
239: g += c;
240: c += Sum0(d) + Maj(d, e, f);
241:
242: // t = 8 * i + 6
243: b += Sum1(g) + Ch(g, h, a) + K[t] + W[t++];
244: f += b;
245: b += Sum0(c) + Maj(c, d, e);
246:
247: // t = 8 * i + 7
248: a += Sum1(f) + Ch(f, g, h) + K[t] + W[t++];
249: e += a;
250: a += Sum0(b) + Maj(b, c, d);
251: }
252:
253: H1 += a;
254: H2 += b;
255: H3 += c;
256: H4 += d;
257: H5 += e;
258: H6 += f;
259: H7 += g;
260: H8 += h;
261:
262: //
263: // reset the offset and clean out the word buffer.
264: //
265: wOff = 0;
266: for (int i = 0; i < 16; i++) {
267: W[i] = 0;
268: }
269: }
270:
271: /* SHA-384 and SHA-512 functions (as for SHA-256 but for longs) */
272: private long Ch(long x, long y, long z) {
273: return ((x & y) ^ ((~x) & z));
274: }
275:
276: private long Maj(long x, long y, long z) {
277: return ((x & y) ^ (x & z) ^ (y & z));
278: }
279:
280: private long Sum0(long x) {
281: return ((x << 36) | (x >>> 28)) ^ ((x << 30) | (x >>> 34))
282: ^ ((x << 25) | (x >>> 39));
283: }
284:
285: private long Sum1(long x) {
286: return ((x << 50) | (x >>> 14)) ^ ((x << 46) | (x >>> 18))
287: ^ ((x << 23) | (x >>> 41));
288: }
289:
290: private long Sigma0(long x) {
291: return ((x << 63) | (x >>> 1)) ^ ((x << 56) | (x >>> 8))
292: ^ (x >>> 7);
293: }
294:
295: private long Sigma1(long x) {
296: return ((x << 45) | (x >>> 19)) ^ ((x << 3) | (x >>> 61))
297: ^ (x >>> 6);
298: }
299:
300: /* SHA-384 and SHA-512 Constants
301: * (represent the first 64 bits of the fractional parts of the
302: * cube roots of the first sixty-four prime numbers)
303: */
304: static final long K[] = { 0x428a2f98d728ae22L, 0x7137449123ef65cdL,
305: 0xb5c0fbcfec4d3b2fL, 0xe9b5dba58189dbbcL,
306: 0x3956c25bf348b538L, 0x59f111f1b605d019L,
307: 0x923f82a4af194f9bL, 0xab1c5ed5da6d8118L,
308: 0xd807aa98a3030242L, 0x12835b0145706fbeL,
309: 0x243185be4ee4b28cL, 0x550c7dc3d5ffb4e2L,
310: 0x72be5d74f27b896fL, 0x80deb1fe3b1696b1L,
311: 0x9bdc06a725c71235L, 0xc19bf174cf692694L,
312: 0xe49b69c19ef14ad2L, 0xefbe4786384f25e3L,
313: 0x0fc19dc68b8cd5b5L, 0x240ca1cc77ac9c65L,
314: 0x2de92c6f592b0275L, 0x4a7484aa6ea6e483L,
315: 0x5cb0a9dcbd41fbd4L, 0x76f988da831153b5L,
316: 0x983e5152ee66dfabL, 0xa831c66d2db43210L,
317: 0xb00327c898fb213fL, 0xbf597fc7beef0ee4L,
318: 0xc6e00bf33da88fc2L, 0xd5a79147930aa725L,
319: 0x06ca6351e003826fL, 0x142929670a0e6e70L,
320: 0x27b70a8546d22ffcL, 0x2e1b21385c26c926L,
321: 0x4d2c6dfc5ac42aedL, 0x53380d139d95b3dfL,
322: 0x650a73548baf63deL, 0x766a0abb3c77b2a8L,
323: 0x81c2c92e47edaee6L, 0x92722c851482353bL,
324: 0xa2bfe8a14cf10364L, 0xa81a664bbc423001L,
325: 0xc24b8b70d0f89791L, 0xc76c51a30654be30L,
326: 0xd192e819d6ef5218L, 0xd69906245565a910L,
327: 0xf40e35855771202aL, 0x106aa07032bbd1b8L,
328: 0x19a4c116b8d2d0c8L, 0x1e376c085141ab53L,
329: 0x2748774cdf8eeb99L, 0x34b0bcb5e19b48a8L,
330: 0x391c0cb3c5c95a63L, 0x4ed8aa4ae3418acbL,
331: 0x5b9cca4f7763e373L, 0x682e6ff3d6b2b8a3L,
332: 0x748f82ee5defb2fcL, 0x78a5636f43172f60L,
333: 0x84c87814a1f0ab72L, 0x8cc702081a6439ecL,
334: 0x90befffa23631e28L, 0xa4506cebde82bde9L,
335: 0xbef9a3f7b2c67915L, 0xc67178f2e372532bL,
336: 0xca273eceea26619cL, 0xd186b8c721c0c207L,
337: 0xeada7dd6cde0eb1eL, 0xf57d4f7fee6ed178L,
338: 0x06f067aa72176fbaL, 0x0a637dc5a2c898a6L,
339: 0x113f9804bef90daeL, 0x1b710b35131c471bL,
340: 0x28db77f523047d84L, 0x32caab7b40c72493L,
341: 0x3c9ebe0a15c9bebcL, 0x431d67c49c100d4cL,
342: 0x4cc5d4becb3e42b6L, 0x597f299cfc657e2aL,
343: 0x5fcb6fab3ad6faecL, 0x6c44198c4a475817L };
344: }
|