1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43:
44:
54: public class Sha512
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: "DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA20A9EEEE64B55D39A"
90: + "2192992A274FC1A836BA3C23A3FEEBBD454D4423643CE80E2A9AC94FA54CA49F";
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 Sha512()
102: {
103: super(Registry.SHA512_HASH, 64, BLOCK_SIZE);
104: }
105:
106:
111: private Sha512(Sha512 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 Sha512(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: (byte)(h6 >>> 56), (byte)(h6 >>> 48), (byte)(h6 >>> 40), (byte)(h6 >>> 32),
190: (byte)(h6 >>> 24), (byte)(h6 >>> 16), (byte)(h6 >>> 8), (byte) h6,
191: (byte)(h7 >>> 56), (byte)(h7 >>> 48), (byte)(h7 >>> 40), (byte)(h7 >>> 32),
192: (byte)(h7 >>> 24), (byte)(h7 >>> 16), (byte)(h7 >>> 8), (byte) h7 };
193: }
194:
195: protected void resetContext()
196: {
197:
198: h0 = 0x6a09e667f3bcc908L;
199: h1 = 0xbb67ae8584caa73bL;
200: h2 = 0x3c6ef372fe94f82bL;
201: h3 = 0xa54ff53a5f1d36f1L;
202: h4 = 0x510e527fade682d1L;
203: h5 = 0x9b05688c2b3e6c1fL;
204: h6 = 0x1f83d9abfb41bd6bL;
205: h7 = 0x5be0cd19137e2179L;
206: }
207:
208: public boolean selfTest()
209: {
210: if (valid == null)
211: {
212: Sha512 md = new Sha512();
213: md.update((byte) 0x61);
214: md.update((byte) 0x62);
215: md.update((byte) 0x63);
216: String result = Util.toString(md.digest());
217: valid = Boolean.valueOf(DIGEST0.equals(result));
218: }
219: return valid.booleanValue();
220: }
221:
222: private static synchronized final long[] sha(long hh0, long hh1, long hh2,
223: long hh3, long hh4, long hh5,
224: long hh6, long hh7, byte[] in,
225: int offset)
226: {
227: long A = hh0;
228: long B = hh1;
229: long C = hh2;
230: long D = hh3;
231: long E = hh4;
232: long F = hh5;
233: long G = hh6;
234: long H = hh7;
235: long T, T2;
236: int r;
237: for (r = 0; r < 16; r++)
238: w[r] = (long) in[offset++] << 56
239: | ((long) in[offset++] & 0xFF) << 48
240: | ((long) in[offset++] & 0xFF) << 40
241: | ((long) in[offset++] & 0xFF) << 32
242: | ((long) in[offset++] & 0xFF) << 24
243: | ((long) in[offset++] & 0xFF) << 16
244: | ((long) in[offset++] & 0xFF) << 8
245: | ((long) in[offset++] & 0xFF);
246: for (r = 16; r < 80; r++)
247: {
248: T = w[r - 2];
249: T2 = w[r - 15];
250: w[r] = (((T >>> 19) | (T << 45)) ^ ((T >>> 61) | (T << 3)) ^ (T >>> 6))
251: + w[r - 7]
252: + (((T2 >>> 1) | (T2 << 63))
253: ^ ((T2 >>> 8) | (T2 << 56))
254: ^ (T2 >>> 7))
255: + w[r - 16];
256: }
257: for (r = 0; r < 80; r++)
258: {
259: T = H
260: + (((E >>> 14) | (E << 50))
261: ^ ((E >>> 18) | (E << 46))
262: ^ ((E >>> 41) | (E << 23)))
263: + ((E & F) ^ ((~E) & G)) + k[r] + w[r];
264: T2 = (((A >>> 28) | (A << 36))
265: ^ ((A >>> 34) | (A << 30))
266: ^ ((A >>> 39) | (A << 25)))
267: + ((A & B) ^ (A & C) ^ (B & C));
268: H = G;
269: G = F;
270: F = E;
271: E = D + T;
272: D = C;
273: C = B;
274: B = A;
275: A = T + T2;
276: }
277: return new long[] {
278: hh0 + A, hh1 + B, hh2 + C, hh3 + D,
279: hh4 + E, hh5 + F, hh6 + G, hh7 + H };
280: }
281: }