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