1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43:
44:
54: public class Sha256
55: extends BaseHash
56: {
57: private static final int[] k = {
58: 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
59: 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
60: 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
61: 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
62: 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
63: 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
64: 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
65: 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
66: 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
67: 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
68: 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
69: 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
70: 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
71: 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
72: 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
73: 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
74: };
75:
76: private static final int BLOCK_SIZE = 64;
77:
78: private static final String DIGEST0 =
79: "BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD";
80:
81: private static final int[] w = new int[64];
82:
83:
84: private static Boolean valid;
85:
86:
87: private int h0, h1, h2, h3, h4, h5, h6, h7;
88:
89:
90: public Sha256()
91: {
92: super(Registry.SHA256_HASH, 32, BLOCK_SIZE);
93: }
94:
95:
100: private Sha256(Sha256 md)
101: {
102: this();
103:
104: this.h0 = md.h0;
105: this.h1 = md.h1;
106: this.h2 = md.h2;
107: this.h3 = md.h3;
108: this.h4 = md.h4;
109: this.h5 = md.h5;
110: this.h6 = md.h6;
111: this.h7 = md.h7;
112: this.count = md.count;
113: this.buffer = (byte[]) md.buffer.clone();
114: }
115:
116: public static final int[] G(int hh0, int hh1, int hh2, int hh3, int hh4,
117: int hh5, int hh6, int hh7, byte[] in, int offset)
118: {
119: return sha(hh0, hh1, hh2, hh3, hh4, hh5, hh6, hh7, in, offset);
120: }
121:
122: public Object clone()
123: {
124: return new Sha256(this);
125: }
126:
127: protected void transform(byte[] in, int offset)
128: {
129: int[] result = sha(h0, h1, h2, h3, h4, h5, h6, h7, in, offset);
130: h0 = result[0];
131: h1 = result[1];
132: h2 = result[2];
133: h3 = result[3];
134: h4 = result[4];
135: h5 = result[5];
136: h6 = result[6];
137: h7 = result[7];
138: }
139:
140: protected byte[] padBuffer()
141: {
142: int n = (int)(count % BLOCK_SIZE);
143: int padding = (n < 56) ? (56 - n) : (120 - n);
144: byte[] result = new byte[padding + 8];
145:
146: result[0] = (byte) 0x80;
147:
148: long bits = count << 3;
149: result[padding++] = (byte)(bits >>> 56);
150: result[padding++] = (byte)(bits >>> 48);
151: result[padding++] = (byte)(bits >>> 40);
152: result[padding++] = (byte)(bits >>> 32);
153: result[padding++] = (byte)(bits >>> 24);
154: result[padding++] = (byte)(bits >>> 16);
155: result[padding++] = (byte)(bits >>> 8);
156: result[padding ] = (byte) bits;
157: return result;
158: }
159:
160: protected byte[] getResult()
161: {
162: return new byte[] {
163: (byte)(h0 >>> 24), (byte)(h0 >>> 16), (byte)(h0 >>> 8), (byte) h0,
164: (byte)(h1 >>> 24), (byte)(h1 >>> 16), (byte)(h1 >>> 8), (byte) h1,
165: (byte)(h2 >>> 24), (byte)(h2 >>> 16), (byte)(h2 >>> 8), (byte) h2,
166: (byte)(h3 >>> 24), (byte)(h3 >>> 16), (byte)(h3 >>> 8), (byte) h3,
167: (byte)(h4 >>> 24), (byte)(h4 >>> 16), (byte)(h4 >>> 8), (byte) h4,
168: (byte)(h5 >>> 24), (byte)(h5 >>> 16), (byte)(h5 >>> 8), (byte) h5,
169: (byte)(h6 >>> 24), (byte)(h6 >>> 16), (byte)(h6 >>> 8), (byte) h6,
170: (byte)(h7 >>> 24), (byte)(h7 >>> 16), (byte)(h7 >>> 8), (byte) h7 };
171: }
172:
173: protected void resetContext()
174: {
175:
176: h0 = 0x6a09e667;
177: h1 = 0xbb67ae85;
178: h2 = 0x3c6ef372;
179: h3 = 0xa54ff53a;
180: h4 = 0x510e527f;
181: h5 = 0x9b05688c;
182: h6 = 0x1f83d9ab;
183: h7 = 0x5be0cd19;
184: }
185:
186: public boolean selfTest()
187: {
188: if (valid == null)
189: {
190: Sha256 md = new Sha256();
191: md.update((byte) 0x61);
192: md.update((byte) 0x62);
193: md.update((byte) 0x63);
194: String result = Util.toString(md.digest());
195: valid = Boolean.valueOf(DIGEST0.equals(result));
196: }
197: return valid.booleanValue();
198: }
199:
200: private static synchronized final int[] sha(int hh0, int hh1, int hh2,
201: int hh3, int hh4, int hh5,
202: int hh6, int hh7, byte[] in,
203: int offset)
204: {
205: int A = hh0;
206: int B = hh1;
207: int C = hh2;
208: int D = hh3;
209: int E = hh4;
210: int F = hh5;
211: int G = hh6;
212: int H = hh7;
213: int r, T, T2;
214: for (r = 0; r < 16; r++)
215: w[r] = (in[offset++] << 24
216: | (in[offset++] & 0xFF) << 16
217: | (in[offset++] & 0xFF) << 8
218: | (in[offset++] & 0xFF));
219: for (r = 16; r < 64; r++)
220: {
221: T = w[r - 2];
222: T2 = w[r - 15];
223: w[r] = ((((T >>> 17) | (T << 15)) ^ ((T >>> 19) | (T << 13)) ^ (T >>> 10))
224: + w[r - 7]
225: + (((T2 >>> 7) | (T2 << 25))
226: ^ ((T2 >>> 18) | (T2 << 14))
227: ^ (T2 >>> 3)) + w[r - 16]);
228: }
229: for (r = 0; r < 64; r++)
230: {
231: T = (H
232: + (((E >>> 6) | (E << 26))
233: ^ ((E >>> 11) | (E << 21))
234: ^ ((E >>> 25) | (E << 7)))
235: + ((E & F) ^ (~E & G)) + k[r] + w[r]);
236: T2 = ((((A >>> 2) | (A << 30))
237: ^ ((A >>> 13) | (A << 19))
238: ^ ((A >>> 22) | (A << 10))) + ((A & B) ^ (A & C) ^ (B & C)));
239: H = G;
240: G = F;
241: F = E;
242: E = D + T;
243: D = C;
244: C = B;
245: B = A;
246: A = T + T2;
247: }
248: return new int[] {
249: hh0 + A, hh1 + B, hh2 + C, hh3 + D,
250: hh4 + E, hh5 + F, hh6 + G, hh7 + H };
251: }
252: }