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