1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43:
44:
54: public class Sha384
55: extends BaseHash
56: {
57: private static final long[] k = {
58: 0x428a2f98d728ae22L, 0x7137449123ef65cdL, 0xb5c0fbcfec4d3b2fL,
59: 0xe9b5dba58189dbbcL, 0x3956c25bf348b538L, 0x59f111f1b605d019L,
60: 0x923f82a4af194f9bL, 0xab1c5ed5da6d8118L, 0xd807aa98a3030242L,
61: 0x12835b0145706fbeL, 0x243185be4ee4b28cL, 0x550c7dc3d5ffb4e2L,
62: 0x72be5d74f27b896fL, 0x80deb1fe3b1696b1L, 0x9bdc06a725c71235L,
63: 0xc19bf174cf692694L, 0xe49b69c19ef14ad2L, 0xefbe4786384f25e3L,
64: 0x0fc19dc68b8cd5b5L, 0x240ca1cc77ac9c65L, 0x2de92c6f592b0275L,
65: 0x4a7484aa6ea6e483L, 0x5cb0a9dcbd41fbd4L, 0x76f988da831153b5L,
66: 0x983e5152ee66dfabL, 0xa831c66d2db43210L, 0xb00327c898fb213fL,
67: 0xbf597fc7beef0ee4L, 0xc6e00bf33da88fc2L, 0xd5a79147930aa725L,
68: 0x06ca6351e003826fL, 0x142929670a0e6e70L, 0x27b70a8546d22ffcL,
69: 0x2e1b21385c26c926L, 0x4d2c6dfc5ac42aedL, 0x53380d139d95b3dfL,
70: 0x650a73548baf63deL, 0x766a0abb3c77b2a8L, 0x81c2c92e47edaee6L,
71: 0x92722c851482353bL, 0xa2bfe8a14cf10364L, 0xa81a664bbc423001L,
72: 0xc24b8b70d0f89791L, 0xc76c51a30654be30L, 0xd192e819d6ef5218L,
73: 0xd69906245565a910L, 0xf40e35855771202aL, 0x106aa07032bbd1b8L,
74: 0x19a4c116b8d2d0c8L, 0x1e376c085141ab53L, 0x2748774cdf8eeb99L,
75: 0x34b0bcb5e19b48a8L, 0x391c0cb3c5c95a63L, 0x4ed8aa4ae3418acbL,
76: 0x5b9cca4f7763e373L, 0x682e6ff3d6b2b8a3L, 0x748f82ee5defb2fcL,
77: 0x78a5636f43172f60L, 0x84c87814a1f0ab72L, 0x8cc702081a6439ecL,
78: 0x90befffa23631e28L, 0xa4506cebde82bde9L, 0xbef9a3f7b2c67915L,
79: 0xc67178f2e372532bL, 0xca273eceea26619cL, 0xd186b8c721c0c207L,
80: 0xeada7dd6cde0eb1eL, 0xf57d4f7fee6ed178L, 0x06f067aa72176fbaL,
81: 0x0a637dc5a2c898a6L, 0x113f9804bef90daeL, 0x1b710b35131c471bL,
82: 0x28db77f523047d84L, 0x32caab7b40c72493L, 0x3c9ebe0a15c9bebcL,
83: 0x431d67c49c100d4cL, 0x4cc5d4becb3e42b6L, 0x597f299cfc657e2aL,
84: 0x5fcb6fab3ad6faecL, 0x6c44198c4a475817L };
85:
86: private static final int BLOCK_SIZE = 128;
87:
88: private static final String DIGEST0 =
89: "CB00753F45A35E8BB5A03D699AC65007272C32AB0EDED1631A8B605A43FF5BED"
90: + "8086072BA1E7CC2358BAECA134C825A7";
91:
92: private static final long[] w = new long[80];
93:
94:
95: private static Boolean valid;
96:
97:
98: private long h0, h1, h2, h3, h4, h5, h6, h7;
99:
100:
101: public Sha384()
102: {
103: super(Registry.SHA384_HASH, 48, BLOCK_SIZE);
104: }
105:
106:
111: private Sha384(Sha384 md)
112: {
113: this();
114:
115: this.h0 = md.h0;
116: this.h1 = md.h1;
117: this.h2 = md.h2;
118: this.h3 = md.h3;
119: this.h4 = md.h4;
120: this.h5 = md.h5;
121: this.h6 = md.h6;
122: this.h7 = md.h7;
123: this.count = md.count;
124: this.buffer = (byte[]) md.buffer.clone();
125: }
126:
127: public static final long[] G(long hh0, long hh1, long hh2, long hh3,
128: long hh4, long hh5, long hh6, long hh7,
129: byte[] in, int offset)
130: {
131: return sha(hh0, hh1, hh2, hh3, hh4, hh5, hh6, hh7, in, offset);
132: }
133:
134: public Object clone()
135: {
136: return new Sha384(this);
137: }
138:
139: protected void transform(byte[] in, int offset)
140: {
141: long[] result = sha(h0, h1, h2, h3, h4, h5, h6, h7, in, offset);
142: h0 = result[0];
143: h1 = result[1];
144: h2 = result[2];
145: h3 = result[3];
146: h4 = result[4];
147: h5 = result[5];
148: h6 = result[6];
149: h7 = result[7];
150: }
151:
152: protected byte[] padBuffer()
153: {
154: int n = (int)(count % BLOCK_SIZE);
155: int padding = (n < 112) ? (112 - n) : (240 - n);
156: byte[] result = new byte[padding + 16];
157:
158: result[0] = (byte) 0x80;
159:
160:
161: long bits = count << 3;
162: padding += 8;
163: result[padding++] = (byte)(bits >>> 56);
164: result[padding++] = (byte)(bits >>> 48);
165: result[padding++] = (byte)(bits >>> 40);
166: result[padding++] = (byte)(bits >>> 32);
167: result[padding++] = (byte)(bits >>> 24);
168: result[padding++] = (byte)(bits >>> 16);
169: result[padding++] = (byte)(bits >>> 8);
170: result[padding ] = (byte) bits;
171: return result;
172: }
173:
174: protected byte[] getResult()
175: {
176: return new byte[] {
177: (byte)(h0 >>> 56), (byte)(h0 >>> 48), (byte)(h0 >>> 40), (byte)(h0 >>> 32),
178: (byte)(h0 >>> 24), (byte)(h0 >>> 16), (byte)(h0 >>> 8), (byte) h0,
179: (byte)(h1 >>> 56), (byte)(h1 >>> 48), (byte)(h1 >>> 40), (byte)(h1 >>> 32),
180: (byte)(h1 >>> 24), (byte)(h1 >>> 16), (byte)(h1 >>> 8), (byte) h1,
181: (byte)(h2 >>> 56), (byte)(h2 >>> 48), (byte)(h2 >>> 40), (byte)(h2 >>> 32),
182: (byte)(h2 >>> 24), (byte)(h2 >>> 16), (byte)(h2 >>> 8), (byte) h2,
183: (byte)(h3 >>> 56), (byte)(h3 >>> 48), (byte)(h3 >>> 40), (byte)(h3 >>> 32),
184: (byte)(h3 >>> 24), (byte)(h3 >>> 16), (byte)(h3 >>> 8), (byte) h3,
185: (byte)(h4 >>> 56), (byte)(h4 >>> 48), (byte)(h4 >>> 40), (byte)(h4 >>> 32),
186: (byte)(h4 >>> 24), (byte)(h4 >>> 16), (byte)(h4 >>> 8), (byte) h4,
187: (byte)(h5 >>> 56), (byte)(h5 >>> 48), (byte)(h5 >>> 40), (byte)(h5 >>> 32),
188: (byte)(h5 >>> 24), (byte)(h5 >>> 16), (byte)(h5 >>> 8), (byte) h5 };
189: }
190:
191: protected void resetContext()
192: {
193:
194: h0 = 0xcbbb9d5dc1059ed8L;
195: h1 = 0x629a292a367cd507L;
196: h2 = 0x9159015a3070dd17L;
197: h3 = 0x152fecd8f70e5939L;
198: h4 = 0x67332667ffc00b31L;
199: h5 = 0x8eb44a8768581511L;
200: h6 = 0xdb0c2e0d64f98fa7L;
201: h7 = 0x47b5481dbefa4fa4L;
202: }
203:
204: public boolean selfTest()
205: {
206: if (valid == null)
207: {
208: Sha384 md = new Sha384();
209: md.update((byte) 0x61);
210: md.update((byte) 0x62);
211: md.update((byte) 0x63);
212: String result = Util.toString(md.digest());
213: valid = Boolean.valueOf(DIGEST0.equals(result));
214: }
215: return valid.booleanValue();
216: }
217:
218: private static synchronized final long[] sha(long hh0, long hh1, long hh2,
219: long hh3, long hh4, long hh5,
220: long hh6, long hh7, byte[] in,
221: int offset)
222: {
223: long A = hh0;
224: long B = hh1;
225: long C = hh2;
226: long D = hh3;
227: long E = hh4;
228: long F = hh5;
229: long G = hh6;
230: long H = hh7;
231: long T, T2;
232: int r;
233: for (r = 0; r < 16; r++)
234: w[r] = (long) in[offset++] << 56
235: | ((long) in[offset++] & 0xFF) << 48
236: | ((long) in[offset++] & 0xFF) << 40
237: | ((long) in[offset++] & 0xFF) << 32
238: | ((long) in[offset++] & 0xFF) << 24
239: | ((long) in[offset++] & 0xFF) << 16
240: | ((long) in[offset++] & 0xFF) << 8
241: | ((long) in[offset++] & 0xFF);
242: for (r = 16; r < 80; r++)
243: {
244: T = w[r - 2];
245: T2 = w[r - 15];
246: w[r] = (((T >>> 19) | (T << 45)) ^ ((T >>> 61) | (T << 3)) ^ (T >>> 6))
247: + w[r - 7]
248: + (((T2 >>> 1) | (T2 << 63))
249: ^ ((T2 >>> 8) | (T2 << 56))
250: ^ (T2 >>> 7))
251: + w[r - 16];
252: }
253: for (r = 0; r < 80; r++)
254: {
255:
256: T = H
257: + (((E >>> 14) | (E << 50))
258: ^ ((E >>> 18) | (E << 46))
259: ^ ((E >>> 41) | (E << 23)))
260: + ((E & F) ^ ((~E) & G)) + k[r] + w[r];
261:
262: T2 = (((A >>> 28) | (A << 36))
263: ^ ((A >>> 34) | (A << 30))
264: ^ ((A >>> 39) | (A << 25)))
265: + ((A & B) ^ (A & C) ^ (B & C));
266: H = G;
267: G = F;
268: F = E;
269: E = D + T;
270: D = C;
271: C = B;
272: B = A;
273: A = T + T2;
274: }
275: return new long[] {
276: hh0 + A, hh1 + B, hh2 + C, hh3 + D,
277: hh4 + E, hh5 + F, hh6 + G, hh7 + H };
278: }
279: }