001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    
018    package org.apache.geronimo.util.crypto.digests;
019    
020    /**
021     * implementation of SHA-1 as outlined in "Handbook of Applied Cryptography", pages 346 - 349.
022     *
023     * It is interesting to ponder why the, apart from the extra IV, the other difference here from MD5
024     * is the "endienness" of the word processing!
025     */
026    public class SHA1Digest
027        extends GeneralDigest
028    {
029        private static final int    DIGEST_LENGTH = 20;
030    
031        private int     H1, H2, H3, H4, H5;
032    
033        private int[]   X = new int[80];
034        private int     xOff;
035    
036        /**
037         * Standard constructor
038         */
039        public SHA1Digest()
040        {
041            reset();
042        }
043    
044        /**
045         * Copy constructor.  This will copy the state of the provided
046         * message digest.
047         */
048        public SHA1Digest(SHA1Digest t)
049        {
050            super(t);
051    
052            H1 = t.H1;
053            H2 = t.H2;
054            H3 = t.H3;
055            H4 = t.H4;
056            H5 = t.H5;
057    
058            System.arraycopy(t.X, 0, X, 0, t.X.length);
059            xOff = t.xOff;
060        }
061    
062        public String getAlgorithmName()
063        {
064            return "SHA-1";
065        }
066    
067        public int getDigestSize()
068        {
069            return DIGEST_LENGTH;
070        }
071    
072        protected void processWord(
073            byte[]  in,
074            int     inOff)
075        {
076            X[xOff++] = (in[inOff] & 0xff) << 24 | (in[inOff + 1] & 0xff) << 16
077                        | (in[inOff + 2] & 0xff) << 8 | in[inOff + 3] & 0xff; 
078    
079            if (xOff == 16)
080            {
081                processBlock();
082            }        
083        }
084    
085        private void unpackWord(
086            int     word,
087            byte[]  out,
088            int     outOff)
089        {
090            out[outOff++] = (byte)(word >>> 24);
091            out[outOff++] = (byte)(word >>> 16);
092            out[outOff++] = (byte)(word >>> 8);
093            out[outOff++] = (byte)word;
094        }
095    
096        protected void processLength(
097            long    bitLength)
098        {
099            if (xOff > 14)
100            {
101                processBlock();
102            }
103    
104            X[14] = (int)(bitLength >>> 32);
105            X[15] = (int)(bitLength & 0xffffffff);
106        }
107    
108        public int doFinal(
109            byte[]  out,
110            int     outOff)
111        {
112            finish();
113    
114            unpackWord(H1, out, outOff);
115            unpackWord(H2, out, outOff + 4);
116            unpackWord(H3, out, outOff + 8);
117            unpackWord(H4, out, outOff + 12);
118            unpackWord(H5, out, outOff + 16);
119    
120            reset();
121    
122            return DIGEST_LENGTH;
123        }
124    
125        /**
126         * reset the chaining variables
127         */
128        public void reset()
129        {
130            super.reset();
131    
132            H1 = 0x67452301;
133            H2 = 0xefcdab89;
134            H3 = 0x98badcfe;
135            H4 = 0x10325476;
136            H5 = 0xc3d2e1f0;
137    
138            xOff = 0;
139            for (int i = 0; i != X.length; i++)
140            {
141                X[i] = 0;
142            }
143        }
144    
145        //
146        // Additive constants
147        //
148        private static final int    Y1 = 0x5a827999;
149        private static final int    Y2 = 0x6ed9eba1;
150        private static final int    Y3 = 0x8f1bbcdc;
151        private static final int    Y4 = 0xca62c1d6;
152       
153        private int f(
154            int    u,
155            int    v,
156            int    w)
157        {
158            return ((u & v) | ((~u) & w));
159        }
160    
161        private int h(
162            int    u,
163            int    v,
164            int    w)
165        {
166            return (u ^ v ^ w);
167        }
168    
169        private int g(
170            int    u,
171            int    v,
172            int    w)
173        {
174            return ((u & v) | (u & w) | (v & w));
175        }
176    
177        protected void processBlock()
178        {
179            //
180            // expand 16 word block into 80 word block.
181            //
182            for (int i = 16; i < 80; i++)
183            {
184                int t = X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16];
185                X[i] = t << 1 | t >>> 31;
186            }
187    
188            //
189            // set up working variables.
190            //
191            int     A = H1;
192            int     B = H2;
193            int     C = H3;
194            int     D = H4;
195            int     E = H5;
196    
197            //
198            // round 1
199            //
200            int idx = 0;
201            
202            for (int j = 0; j < 4; j++)
203            {
204                // E = rotateLeft(A, 5) + f(B, C, D) + E + X[idx++] + Y1
205                // B = rotateLeft(B, 30)
206                E += (A << 5 | A >>> 27) + f(B, C, D) + X[idx++] + Y1;
207                B = B << 30 | B >>> 2;
208            
209                D += (E << 5 | E >>> 27) + f(A, B, C) + X[idx++] + Y1;
210                A = A << 30 | A >>> 2;
211           
212                C += (D << 5 | D >>> 27) + f(E, A, B) + X[idx++] + Y1;
213                E = E << 30 | E >>> 2;
214           
215                B += (C << 5 | C >>> 27) + f(D, E, A) + X[idx++] + Y1;
216                D = D << 30 | D >>> 2;
217    
218                A += (B << 5 | B >>> 27) + f(C, D, E) + X[idx++] + Y1;
219                C = C << 30 | C >>> 2;
220            }
221            
222            //
223            // round 2
224            //
225            for (int j = 0; j < 4; j++)
226            {
227                // E = rotateLeft(A, 5) + h(B, C, D) + E + X[idx++] + Y2
228                // B = rotateLeft(B, 30)
229                E += (A << 5 | A >>> 27) + h(B, C, D) + X[idx++] + Y2;
230                B = B << 30 | B >>> 2;   
231                
232                D += (E << 5 | E >>> 27) + h(A, B, C) + X[idx++] + Y2;
233                A = A << 30 | A >>> 2;
234                
235                C += (D << 5 | D >>> 27) + h(E, A, B) + X[idx++] + Y2;
236                E = E << 30 | E >>> 2;
237                
238                B += (C << 5 | C >>> 27) + h(D, E, A) + X[idx++] + Y2;
239                D = D << 30 | D >>> 2;
240    
241                A += (B << 5 | B >>> 27) + h(C, D, E) + X[idx++] + Y2;
242                C = C << 30 | C >>> 2;
243            }
244            
245            //
246            // round 3
247            //
248            for (int j = 0; j < 4; j++)
249            {
250                // E = rotateLeft(A, 5) + g(B, C, D) + E + X[idx++] + Y3
251                // B = rotateLeft(B, 30)
252                E += (A << 5 | A >>> 27) + g(B, C, D) + X[idx++] + Y3;
253                B = B << 30 | B >>> 2;
254                
255                D += (E << 5 | E >>> 27) + g(A, B, C) + X[idx++] + Y3;
256                A = A << 30 | A >>> 2;
257                
258                C += (D << 5 | D >>> 27) + g(E, A, B) + X[idx++] + Y3;
259                E = E << 30 | E >>> 2;
260                
261                B += (C << 5 | C >>> 27) + g(D, E, A) + X[idx++] + Y3;
262                D = D << 30 | D >>> 2;
263    
264                A += (B << 5 | B >>> 27) + g(C, D, E) + X[idx++] + Y3;
265                C = C << 30 | C >>> 2;
266            }
267    
268            //
269            // round 4
270            //
271            for (int j = 0; j <= 3; j++)
272            {
273                // E = rotateLeft(A, 5) + h(B, C, D) + E + X[idx++] + Y4
274                // B = rotateLeft(B, 30)
275                E += (A << 5 | A >>> 27) + h(B, C, D) + X[idx++] + Y4;
276                B = B << 30 | B >>> 2;
277                
278                D += (E << 5 | E >>> 27) + h(A, B, C) + X[idx++] + Y4;
279                A = A << 30 | A >>> 2;
280                
281                C += (D << 5 | D >>> 27) + h(E, A, B) + X[idx++] + Y4;
282                E = E << 30 | E >>> 2;
283                
284                B += (C << 5 | C >>> 27) + h(D, E, A) + X[idx++] + Y4;
285                D = D << 30 | D >>> 2;
286    
287                A += (B << 5 | B >>> 27) + h(C, D, E) + X[idx++] + Y4;
288                C = C << 30 | C >>> 2;
289            }
290    
291    
292            H1 += A;
293            H2 += B;
294            H3 += C;
295            H4 += D;
296            H5 += E;
297    
298            //
299            // reset start of the buffer.
300            //
301            xOff = 0;
302            for (int i = 0; i < 16; i++)
303            {
304                X[i] = 0;
305            }
306        }
307    }
308    
309    
310    
311