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