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