2003/06/16 08:03:15
[org.ibex.core.git] / src / org / bouncycastle / crypto / digests / SHA1Digest.java
1 package org.bouncycastle.crypto.digests;
2
3 import org.bouncycastle.crypto.Digest;
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  */
11 public 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         X[xOff++] = ((in[inOff] & 0xff) << 24) | ((in[inOff + 1] & 0xff) << 16)
62                     | ((in[inOff + 2] & 0xff) << 8) | ((in[inOff + 3] & 0xff)); 
63
64         if (xOff == 16)
65         {
66             processBlock();
67         }
68     }
69
70     private void unpackWord(
71         int     word,
72         byte[]  out,
73         int     outOff)
74     {
75         out[outOff]     = (byte)(word >>> 24);
76         out[outOff + 1] = (byte)(word >>> 16);
77         out[outOff + 2] = (byte)(word >>> 8);
78         out[outOff + 3] = (byte)word;
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         unpackWord(H1, out, outOff);
100         unpackWord(H2, out, outOff + 4);
101         unpackWord(H3, out, outOff + 8);
102         unpackWord(H4, out, outOff + 12);
103         unpackWord(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     private int rotateLeft(
163         int    x,
164         int    n)
165     {
166         return (x << n) | (x >>> (32 - n));
167     }
168
169     protected void processBlock()
170     {
171         //
172         // expand 16 word block into 80 word block.
173         //
174         for (int i = 16; i <= 79; i++)
175         {
176             X[i] = rotateLeft((X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16]), 1);
177         }
178
179         //
180         // set up working variables.
181         //
182         int     A = H1;
183         int     B = H2;
184         int     C = H3;
185         int     D = H4;
186         int     E = H5;
187
188         //
189         // round 1
190         //
191         for (int j = 0; j <= 19; j++)
192         {
193             int     t = rotateLeft(A, 5) + f(B, C, D) + E + X[j] + Y1;
194
195             E = D;
196             D = C;
197             C = rotateLeft(B, 30);
198             B = A;
199             A = t;
200         }
201
202         //
203         // round 2
204         //
205         for (int j = 20; j <= 39; j++)
206         {
207             int     t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y2;
208
209             E = D;
210             D = C;
211             C = rotateLeft(B, 30);
212             B = A;
213             A = t;
214         }
215
216         //
217         // round 3
218         //
219         for (int j = 40; j <= 59; j++)
220         {
221             int     t = rotateLeft(A, 5) + g(B, C, D) + E + X[j] + Y3;
222
223             E = D;
224             D = C;
225             C = rotateLeft(B, 30);
226             B = A;
227             A = t;
228         }
229
230         //
231         // round 4
232         //
233         for (int j = 60; j <= 79; j++)
234         {
235             int     t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y4;
236
237             E = D;
238             D = C;
239             C = rotateLeft(B, 30);
240             B = A;
241             A = t;
242         }
243
244         H1 += A;
245         H2 += B;
246         H3 += C;
247         H4 += D;
248         H5 += E;
249
250         //
251         // reset the offset and clean out the word buffer.
252         //
253         xOff = 0;
254         for (int i = 0; i != X.length; i++)
255         {
256             X[i] = 0;
257         }
258     }
259 }