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++] = (byte)(word >>> 16); 75 out[outOff++] = (byte)(word >>> 8); 76 out[outOff++] = (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 protected void processBlock() 161 { 162 // 163 // expand 16 word block into 80 word block. 164 // 165 for (int i = 16; i < 80; i++) 166 { 167 int t = X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16]; 168 X[i] = t << 1 | t >>> 31; 169 } 170 171 // 172 // set up working variables. 173 // 174 int A = H1; 175 int B = H2; 176 int C = H3; 177 int D = H4; 178 int E = H5; 179 180 // 181 // round 1 182 // 183 int idx = 0; 184 185 for (int j = 0; j < 4; j++) 186 { 187 // E = rotateLeft(A, 5) + f(B, C, D) + E + X[idx++] + Y1 188 // B = rotateLeft(B, 30) 189 E += (A << 5 | A >>> 27) + f(B, C, D) + X[idx++] + Y1; 190 B = B << 30 | B >>> 2; 191 192 D += (E << 5 | E >>> 27) + f(A, B, C) + X[idx++] + Y1; 193 A = A << 30 | A >>> 2; 194 195 C += (D << 5 | D >>> 27) + f(E, A, B) + X[idx++] + Y1; 196 E = E << 30 | E >>> 2; 197 198 B += (C << 5 | C >>> 27) + f(D, E, A) + X[idx++] + Y1; 199 D = D << 30 | D >>> 2; 200 201 A += (B << 5 | B >>> 27) + f(C, D, E) + X[idx++] + Y1; 202 C = C << 30 | C >>> 2; 203 } 204 205 // 206 // round 2 207 // 208 for (int j = 0; j < 4; j++) 209 { 210 // E = rotateLeft(A, 5) + h(B, C, D) + E + X[idx++] + Y2 211 // B = rotateLeft(B, 30) 212 E += (A << 5 | A >>> 27) + h(B, C, D) + X[idx++] + Y2; 213 B = B << 30 | B >>> 2; 214 215 D += (E << 5 | E >>> 27) + h(A, B, C) + X[idx++] + Y2; 216 A = A << 30 | A >>> 2; 217 218 C += (D << 5 | D >>> 27) + h(E, A, B) + X[idx++] + Y2; 219 E = E << 30 | E >>> 2; 220 221 B += (C << 5 | C >>> 27) + h(D, E, A) + X[idx++] + Y2; 222 D = D << 30 | D >>> 2; 223 224 A += (B << 5 | B >>> 27) + h(C, D, E) + X[idx++] + Y2; 225 C = C << 30 | C >>> 2; 226 } 227 228 // 229 // round 3 230 // 231 for (int j = 0; j < 4; j++) 232 { 233 // E = rotateLeft(A, 5) + g(B, C, D) + E + X[idx++] + Y3 234 // B = rotateLeft(B, 30) 235 E += (A << 5 | A >>> 27) + g(B, C, D) + X[idx++] + Y3; 236 B = B << 30 | B >>> 2; 237 238 D += (E << 5 | E >>> 27) + g(A, B, C) + X[idx++] + Y3; 239 A = A << 30 | A >>> 2; 240 241 C += (D << 5 | D >>> 27) + g(E, A, B) + X[idx++] + Y3; 242 E = E << 30 | E >>> 2; 243 244 B += (C << 5 | C >>> 27) + g(D, E, A) + X[idx++] + Y3; 245 D = D << 30 | D >>> 2; 246 247 A += (B << 5 | B >>> 27) + g(C, D, E) + X[idx++] + Y3; 248 C = C << 30 | C >>> 2; 249 } 250 251 // 252 // round 4 253 // 254 for (int j = 0; j <= 3; j++) 255 { 256 // E = rotateLeft(A, 5) + h(B, C, D) + E + X[idx++] + Y4 257 // B = rotateLeft(B, 30) 258 E += (A << 5 | A >>> 27) + h(B, C, D) + X[idx++] + Y4; 259 B = B << 30 | B >>> 2; 260 261 D += (E << 5 | E >>> 27) + h(A, B, C) + X[idx++] + Y4; 262 A = A << 30 | A >>> 2; 263 264 C += (D << 5 | D >>> 27) + h(E, A, B) + X[idx++] + Y4; 265 E = E << 30 | E >>> 2; 266 267 B += (C << 5 | C >>> 27) + h(D, E, A) + X[idx++] + Y4; 268 D = D << 30 | D >>> 2; 269 270 A += (B << 5 | B >>> 27) + h(C, D, E) + X[idx++] + Y4; 271 C = C << 30 | C >>> 2; 272 } 273 274 275 H1 += A; 276 H2 += B; 277 H3 += C; 278 H4 += D; 279 H5 += E; 280 281 // 282 // reset start of the buffer. 283 // 284 xOff = 0; 285 for (int i = 0; i < 16; i++) 286 { 287 X[i] = 0; 288 } 289 } 290 } 291 292 293 294 295