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