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