1 package org.bouncycastle.crypto.digests;
2 
3 
4 import org.bouncycastle.util.Memoable;
5 import org.bouncycastle.util.Pack;
6 
7 
8 /**
9  * FIPS 180-2 implementation of SHA-256.
10  *
11  * <pre>
12  *         block  word  digest
13  * SHA-1   512    32    160
14  * SHA-256 512    32    256
15  * SHA-384 1024   64    384
16  * SHA-512 1024   64    512
17  * </pre>
18  */
19 public class SHA256Digest
20     extends GeneralDigest
21     implements EncodableDigest
22 {
23     private static final int    DIGEST_LENGTH = 32;
24 
25     private int     H1, H2, H3, H4, H5, H6, H7, H8;
26 
27     private int[]   X = new int[64];
28     private int     xOff;
29 
30     /**
31      * Standard constructor
32      */
SHA256Digest()33     public SHA256Digest()
34     {
35         reset();
36     }
37 
38     /**
39      * Copy constructor.  This will copy the state of the provided
40      * message digest.
41      */
SHA256Digest(SHA256Digest t)42     public SHA256Digest(SHA256Digest t)
43     {
44         super(t);
45 
46         copyIn(t);
47     }
48 
copyIn(SHA256Digest t)49     private void copyIn(SHA256Digest t)
50     {
51         super.copyIn(t);
52 
53         H1 = t.H1;
54         H2 = t.H2;
55         H3 = t.H3;
56         H4 = t.H4;
57         H5 = t.H5;
58         H6 = t.H6;
59         H7 = t.H7;
60         H8 = t.H8;
61 
62         System.arraycopy(t.X, 0, X, 0, t.X.length);
63         xOff = t.xOff;
64     }
65 
66     /**
67      * State constructor - create a digest initialised with the state of a previous one.
68      *
69      * @param encodedState the encoded state from the originating digest.
70      */
SHA256Digest(byte[] encodedState)71     public SHA256Digest(byte[] encodedState)
72     {
73         super(encodedState);
74 
75         H1 = Pack.bigEndianToInt(encodedState, 16);
76         H2 = Pack.bigEndianToInt(encodedState, 20);
77         H3 = Pack.bigEndianToInt(encodedState, 24);
78         H4 = Pack.bigEndianToInt(encodedState, 28);
79         H5 = Pack.bigEndianToInt(encodedState, 32);
80         H6 = Pack.bigEndianToInt(encodedState, 36);
81         H7 = Pack.bigEndianToInt(encodedState, 40);
82         H8 = Pack.bigEndianToInt(encodedState, 44);
83 
84         xOff = Pack.bigEndianToInt(encodedState, 48);
85         for (int i = 0; i != xOff; i++)
86         {
87             X[i] = Pack.bigEndianToInt(encodedState, 52 + (i * 4));
88         }
89     }
90 
91 
getAlgorithmName()92     public String getAlgorithmName()
93     {
94         return "SHA-256";
95     }
96 
getDigestSize()97     public int getDigestSize()
98     {
99         return DIGEST_LENGTH;
100     }
101 
processWord( byte[] in, int inOff)102     protected void processWord(
103         byte[]  in,
104         int     inOff)
105     {
106         // Note: Inlined for performance
107 //        X[xOff] = Pack.bigEndianToInt(in, inOff);
108         int n = in[inOff] << 24;
109         n |= (in[++inOff] & 0xff) << 16;
110         n |= (in[++inOff] & 0xff) << 8;
111         n |= (in[++inOff] & 0xff);
112         X[xOff] = n;
113 
114         if (++xOff == 16)
115         {
116             processBlock();
117         }
118     }
119 
processLength( long bitLength)120     protected void processLength(
121         long    bitLength)
122     {
123         if (xOff > 14)
124         {
125             processBlock();
126         }
127 
128         X[14] = (int)(bitLength >>> 32);
129         X[15] = (int)(bitLength & 0xffffffff);
130     }
131 
doFinal( byte[] out, int outOff)132     public int doFinal(
133         byte[]  out,
134         int     outOff)
135     {
136         finish();
137 
138         Pack.intToBigEndian(H1, out, outOff);
139         Pack.intToBigEndian(H2, out, outOff + 4);
140         Pack.intToBigEndian(H3, out, outOff + 8);
141         Pack.intToBigEndian(H4, out, outOff + 12);
142         Pack.intToBigEndian(H5, out, outOff + 16);
143         Pack.intToBigEndian(H6, out, outOff + 20);
144         Pack.intToBigEndian(H7, out, outOff + 24);
145         Pack.intToBigEndian(H8, out, outOff + 28);
146 
147         reset();
148 
149         return DIGEST_LENGTH;
150     }
151 
152     /**
153      * reset the chaining variables
154      */
reset()155     public void reset()
156     {
157         super.reset();
158 
159         /* SHA-256 initial hash value
160          * The first 32 bits of the fractional parts of the square roots
161          * of the first eight prime numbers
162          */
163 
164         H1 = 0x6a09e667;
165         H2 = 0xbb67ae85;
166         H3 = 0x3c6ef372;
167         H4 = 0xa54ff53a;
168         H5 = 0x510e527f;
169         H6 = 0x9b05688c;
170         H7 = 0x1f83d9ab;
171         H8 = 0x5be0cd19;
172 
173         xOff = 0;
174         for (int i = 0; i != X.length; i++)
175         {
176             X[i] = 0;
177         }
178     }
179 
processBlock()180     protected void processBlock()
181     {
182         //
183         // expand 16 word block into 64 word blocks.
184         //
185         for (int t = 16; t <= 63; t++)
186         {
187             X[t] = Theta1(X[t - 2]) + X[t - 7] + Theta0(X[t - 15]) + X[t - 16];
188         }
189 
190         //
191         // set up working variables.
192         //
193         int     a = H1;
194         int     b = H2;
195         int     c = H3;
196         int     d = H4;
197         int     e = H5;
198         int     f = H6;
199         int     g = H7;
200         int     h = H8;
201 
202         int t = 0;
203         for(int i = 0; i < 8; i ++)
204         {
205             // t = 8 * i
206             h += Sum1(e) + Ch(e, f, g) + K[t] + X[t];
207             d += h;
208             h += Sum0(a) + Maj(a, b, c);
209             ++t;
210 
211             // t = 8 * i + 1
212             g += Sum1(d) + Ch(d, e, f) + K[t] + X[t];
213             c += g;
214             g += Sum0(h) + Maj(h, a, b);
215             ++t;
216 
217             // t = 8 * i + 2
218             f += Sum1(c) + Ch(c, d, e) + K[t] + X[t];
219             b += f;
220             f += Sum0(g) + Maj(g, h, a);
221             ++t;
222 
223             // t = 8 * i + 3
224             e += Sum1(b) + Ch(b, c, d) + K[t] + X[t];
225             a += e;
226             e += Sum0(f) + Maj(f, g, h);
227             ++t;
228 
229             // t = 8 * i + 4
230             d += Sum1(a) + Ch(a, b, c) + K[t] + X[t];
231             h += d;
232             d += Sum0(e) + Maj(e, f, g);
233             ++t;
234 
235             // t = 8 * i + 5
236             c += Sum1(h) + Ch(h, a, b) + K[t] + X[t];
237             g += c;
238             c += Sum0(d) + Maj(d, e, f);
239             ++t;
240 
241             // t = 8 * i + 6
242             b += Sum1(g) + Ch(g, h, a) + K[t] + X[t];
243             f += b;
244             b += Sum0(c) + Maj(c, d, e);
245             ++t;
246 
247             // t = 8 * i + 7
248             a += Sum1(f) + Ch(f, g, h) + K[t] + X[t];
249             e += a;
250             a += Sum0(b) + Maj(b, c, d);
251             ++t;
252         }
253 
254         H1 += a;
255         H2 += b;
256         H3 += c;
257         H4 += d;
258         H5 += e;
259         H6 += f;
260         H7 += g;
261         H8 += h;
262 
263         //
264         // reset the offset and clean out the word buffer.
265         //
266         xOff = 0;
267         for (int i = 0; i < 16; i++)
268         {
269             X[i] = 0;
270         }
271     }
272 
273     /* SHA-256 functions */
Ch(int x, int y, int z)274     private static int Ch(int x, int y, int z)
275     {
276         return (x & y) ^ ((~x) & z);
277 //        return z ^ (x & (y ^ z));
278     }
279 
Maj(int x, int y, int z)280     private static int Maj(int x, int y, int z)
281     {
282 //        return (x & y) ^ (x & z) ^ (y & z);
283         return (x & y) | (z & (x ^ y));
284     }
285 
Sum0(int x)286     private static int Sum0(int x)
287     {
288         return ((x >>> 2) | (x << 30)) ^ ((x >>> 13) | (x << 19)) ^ ((x >>> 22) | (x << 10));
289     }
290 
Sum1(int x)291     private static int Sum1(int x)
292     {
293         return ((x >>> 6) | (x << 26)) ^ ((x >>> 11) | (x << 21)) ^ ((x >>> 25) | (x << 7));
294     }
295 
Theta0(int x)296     private static int Theta0(int x)
297     {
298         return ((x >>> 7) | (x << 25)) ^ ((x >>> 18) | (x << 14)) ^ (x >>> 3);
299     }
300 
Theta1(int x)301     private static int Theta1(int x)
302     {
303         return ((x >>> 17) | (x << 15)) ^ ((x >>> 19) | (x << 13)) ^ (x >>> 10);
304     }
305 
306     /* SHA-256 Constants
307      * (represent the first 32 bits of the fractional parts of the
308      * cube roots of the first sixty-four prime numbers)
309      */
310     static final int K[] = {
311         0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
312         0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
313         0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
314         0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
315         0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
316         0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
317         0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
318         0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
319     };
320 
copy()321     public Memoable copy()
322     {
323         return new SHA256Digest(this);
324     }
325 
reset(Memoable other)326     public void reset(Memoable other)
327     {
328         SHA256Digest d = (SHA256Digest)other;
329 
330         copyIn(d);
331     }
332 
getEncodedState()333     public byte[] getEncodedState()
334     {
335         byte[] state = new byte[52 + xOff * 4];
336 
337         super.populateState(state);
338 
339         Pack.intToBigEndian(H1, state, 16);
340         Pack.intToBigEndian(H2, state, 20);
341         Pack.intToBigEndian(H3, state, 24);
342         Pack.intToBigEndian(H4, state, 28);
343         Pack.intToBigEndian(H5, state, 32);
344         Pack.intToBigEndian(H6, state, 36);
345         Pack.intToBigEndian(H7, state, 40);
346         Pack.intToBigEndian(H8, state, 44);
347         Pack.intToBigEndian(xOff, state, 48);
348 
349         for (int i = 0; i != xOff; i++)
350         {
351             Pack.intToBigEndian(X[i], state, 52 + (i * 4));
352         }
353 
354         return state;
355     }
356 }
357 
358