SHA1Digest.java revision a198e1ecc615e26a167d0f2dca9fa7e5fc62de10
1package org.bouncycastle.crypto.digests;
2
3import org.bouncycastle.crypto.util.Pack;
4import org.bouncycastle.util.Memoable;
5
6/**
7 * implementation of SHA-1 as outlined in "Handbook of Applied Cryptography", pages 346 - 349.
8 *
9 * It is interesting to ponder why the, apart from the extra IV, the other difference here from MD5
10 * is the "endianness" of the word processing!
11 */
12public class SHA1Digest
13    extends GeneralDigest
14{
15    private static final int    DIGEST_LENGTH = 20;
16
17    private int     H1, H2, H3, H4, H5;
18
19    private int[]   X = new int[80];
20    private int     xOff;
21
22    /**
23     * Standard constructor
24     */
25    public SHA1Digest()
26    {
27        reset();
28    }
29
30    /**
31     * Copy constructor.  This will copy the state of the provided
32     * message digest.
33     */
34    public SHA1Digest(SHA1Digest t)
35    {
36        super(t);
37
38        copyIn(t);
39    }
40
41    private void copyIn(SHA1Digest t)
42    {
43        H1 = t.H1;
44        H2 = t.H2;
45        H3 = t.H3;
46        H4 = t.H4;
47        H5 = t.H5;
48
49        System.arraycopy(t.X, 0, X, 0, t.X.length);
50        xOff = t.xOff;
51    }
52
53    public String getAlgorithmName()
54    {
55        return "SHA-1";
56    }
57
58    public int getDigestSize()
59    {
60        return DIGEST_LENGTH;
61    }
62
63    protected void processWord(
64        byte[]  in,
65        int     inOff)
66    {
67        // Note: Inlined for performance
68//        X[xOff] = Pack.bigEndianToInt(in, inOff);
69        int n = in[  inOff] << 24;
70        n |= (in[++inOff] & 0xff) << 16;
71        n |= (in[++inOff] & 0xff) << 8;
72        n |= (in[++inOff] & 0xff);
73        X[xOff] = n;
74
75        if (++xOff == 16)
76        {
77            processBlock();
78        }
79    }
80
81    protected void processLength(
82        long    bitLength)
83    {
84        if (xOff > 14)
85        {
86            processBlock();
87        }
88
89        X[14] = (int)(bitLength >>> 32);
90        X[15] = (int)(bitLength & 0xffffffff);
91    }
92
93    public int doFinal(
94        byte[]  out,
95        int     outOff)
96    {
97        finish();
98
99        Pack.intToBigEndian(H1, out, outOff);
100        Pack.intToBigEndian(H2, out, outOff + 4);
101        Pack.intToBigEndian(H3, out, outOff + 8);
102        Pack.intToBigEndian(H4, out, outOff + 12);
103        Pack.intToBigEndian(H5, out, outOff + 16);
104
105        reset();
106
107        return DIGEST_LENGTH;
108    }
109
110    /**
111     * reset the chaining variables
112     */
113    public void reset()
114    {
115        super.reset();
116
117        H1 = 0x67452301;
118        H2 = 0xefcdab89;
119        H3 = 0x98badcfe;
120        H4 = 0x10325476;
121        H5 = 0xc3d2e1f0;
122
123        xOff = 0;
124        for (int i = 0; i != X.length; i++)
125        {
126            X[i] = 0;
127        }
128    }
129
130    //
131    // Additive constants
132    //
133    private static final int    Y1 = 0x5a827999;
134    private static final int    Y2 = 0x6ed9eba1;
135    private static final int    Y3 = 0x8f1bbcdc;
136    private static final int    Y4 = 0xca62c1d6;
137
138    private int f(
139        int    u,
140        int    v,
141        int    w)
142    {
143        return ((u & v) | ((~u) & w));
144    }
145
146    private int h(
147        int    u,
148        int    v,
149        int    w)
150    {
151        return (u ^ v ^ w);
152    }
153
154    private int g(
155        int    u,
156        int    v,
157        int    w)
158    {
159        return ((u & v) | (u & w) | (v & w));
160    }
161
162    protected void processBlock()
163    {
164        //
165        // expand 16 word block into 80 word block.
166        //
167        for (int i = 16; i < 80; i++)
168        {
169            int t = X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16];
170            X[i] = t << 1 | t >>> 31;
171        }
172
173        //
174        // set up working variables.
175        //
176        int     A = H1;
177        int     B = H2;
178        int     C = H3;
179        int     D = H4;
180        int     E = H5;
181
182        //
183        // round 1
184        //
185        int idx = 0;
186
187        for (int j = 0; j < 4; j++)
188        {
189            // E = rotateLeft(A, 5) + f(B, C, D) + E + X[idx++] + Y1
190            // B = rotateLeft(B, 30)
191            E += (A << 5 | A >>> 27) + f(B, C, D) + X[idx++] + Y1;
192            B = B << 30 | B >>> 2;
193
194            D += (E << 5 | E >>> 27) + f(A, B, C) + X[idx++] + Y1;
195            A = A << 30 | A >>> 2;
196
197            C += (D << 5 | D >>> 27) + f(E, A, B) + X[idx++] + Y1;
198            E = E << 30 | E >>> 2;
199
200            B += (C << 5 | C >>> 27) + f(D, E, A) + X[idx++] + Y1;
201            D = D << 30 | D >>> 2;
202
203            A += (B << 5 | B >>> 27) + f(C, D, E) + X[idx++] + Y1;
204            C = C << 30 | C >>> 2;
205        }
206
207        //
208        // round 2
209        //
210        for (int j = 0; j < 4; j++)
211        {
212            // E = rotateLeft(A, 5) + h(B, C, D) + E + X[idx++] + Y2
213            // B = rotateLeft(B, 30)
214            E += (A << 5 | A >>> 27) + h(B, C, D) + X[idx++] + Y2;
215            B = B << 30 | B >>> 2;
216
217            D += (E << 5 | E >>> 27) + h(A, B, C) + X[idx++] + Y2;
218            A = A << 30 | A >>> 2;
219
220            C += (D << 5 | D >>> 27) + h(E, A, B) + X[idx++] + Y2;
221            E = E << 30 | E >>> 2;
222
223            B += (C << 5 | C >>> 27) + h(D, E, A) + X[idx++] + Y2;
224            D = D << 30 | D >>> 2;
225
226            A += (B << 5 | B >>> 27) + h(C, D, E) + X[idx++] + Y2;
227            C = C << 30 | C >>> 2;
228        }
229
230        //
231        // round 3
232        //
233        for (int j = 0; j < 4; j++)
234        {
235            // E = rotateLeft(A, 5) + g(B, C, D) + E + X[idx++] + Y3
236            // B = rotateLeft(B, 30)
237            E += (A << 5 | A >>> 27) + g(B, C, D) + X[idx++] + Y3;
238            B = B << 30 | B >>> 2;
239
240            D += (E << 5 | E >>> 27) + g(A, B, C) + X[idx++] + Y3;
241            A = A << 30 | A >>> 2;
242
243            C += (D << 5 | D >>> 27) + g(E, A, B) + X[idx++] + Y3;
244            E = E << 30 | E >>> 2;
245
246            B += (C << 5 | C >>> 27) + g(D, E, A) + X[idx++] + Y3;
247            D = D << 30 | D >>> 2;
248
249            A += (B << 5 | B >>> 27) + g(C, D, E) + X[idx++] + Y3;
250            C = C << 30 | C >>> 2;
251        }
252
253        //
254        // round 4
255        //
256        for (int j = 0; j <= 3; j++)
257        {
258            // E = rotateLeft(A, 5) + h(B, C, D) + E + X[idx++] + Y4
259            // B = rotateLeft(B, 30)
260            E += (A << 5 | A >>> 27) + h(B, C, D) + X[idx++] + Y4;
261            B = B << 30 | B >>> 2;
262
263            D += (E << 5 | E >>> 27) + h(A, B, C) + X[idx++] + Y4;
264            A = A << 30 | A >>> 2;
265
266            C += (D << 5 | D >>> 27) + h(E, A, B) + X[idx++] + Y4;
267            E = E << 30 | E >>> 2;
268
269            B += (C << 5 | C >>> 27) + h(D, E, A) + X[idx++] + Y4;
270            D = D << 30 | D >>> 2;
271
272            A += (B << 5 | B >>> 27) + h(C, D, E) + X[idx++] + Y4;
273            C = C << 30 | C >>> 2;
274        }
275
276
277        H1 += A;
278        H2 += B;
279        H3 += C;
280        H4 += D;
281        H5 += E;
282
283        //
284        // reset start of the buffer.
285        //
286        xOff = 0;
287        for (int i = 0; i < 16; i++)
288        {
289            X[i] = 0;
290        }
291    }
292
293    public Memoable copy()
294    {
295        return new SHA1Digest(this);
296    }
297
298    public void reset(Memoable other)
299    {
300        SHA1Digest d = (SHA1Digest)other;
301
302        super.copyIn(d);
303        copyIn(d);
304    }
305}
306
307
308
309
310