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