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