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