1 package org.bouncycastle.crypto.digests; 2 3 import org.bouncycastle.util.Memoable; 4 import org.bouncycastle.util.Pack; 5 6 /** 7 * implementation of SHA-1 as outlined in "Handbook of Applied Cryptography", pages 346 - 349. 8 * 9 * It is interesting to ponder why the, apart from the extra IV, the other difference here from MD5 10 * is the "endianness" of the word processing! 11 */ 12 public class SHA1Digest 13 extends GeneralDigest 14 implements EncodableDigest 15 { 16 private static final int DIGEST_LENGTH = 20; 17 18 private int H1, H2, H3, H4, H5; 19 20 private int[] X = new int[80]; 21 private int xOff; 22 23 /** 24 * Standard constructor 25 */ SHA1Digest()26 public SHA1Digest() 27 { 28 reset(); 29 } 30 31 /** 32 * Copy constructor. This will copy the state of the provided 33 * message digest. 34 */ SHA1Digest(SHA1Digest t)35 public SHA1Digest(SHA1Digest t) 36 { 37 super(t); 38 39 copyIn(t); 40 } 41 SHA1Digest(byte[] encodedState)42 public SHA1Digest(byte[] encodedState) 43 { 44 super(encodedState); 45 46 H1 = Pack.bigEndianToInt(encodedState, 16); 47 H2 = Pack.bigEndianToInt(encodedState, 20); 48 H3 = Pack.bigEndianToInt(encodedState, 24); 49 H4 = Pack.bigEndianToInt(encodedState, 28); 50 H5 = Pack.bigEndianToInt(encodedState, 32); 51 52 xOff = Pack.bigEndianToInt(encodedState, 36); 53 for (int i = 0; i != xOff; i++) 54 { 55 X[i] = Pack.bigEndianToInt(encodedState, 40 + (i * 4)); 56 } 57 } 58 copyIn(SHA1Digest t)59 private void copyIn(SHA1Digest t) 60 { 61 H1 = t.H1; 62 H2 = t.H2; 63 H3 = t.H3; 64 H4 = t.H4; 65 H5 = t.H5; 66 67 System.arraycopy(t.X, 0, X, 0, t.X.length); 68 xOff = t.xOff; 69 } 70 getAlgorithmName()71 public String getAlgorithmName() 72 { 73 return "SHA-1"; 74 } 75 getDigestSize()76 public int getDigestSize() 77 { 78 return DIGEST_LENGTH; 79 } 80 processWord( byte[] in, int inOff)81 protected void processWord( 82 byte[] in, 83 int inOff) 84 { 85 // Note: Inlined for performance 86 // X[xOff] = Pack.bigEndianToInt(in, inOff); 87 int n = in[ inOff] << 24; 88 n |= (in[++inOff] & 0xff) << 16; 89 n |= (in[++inOff] & 0xff) << 8; 90 n |= (in[++inOff] & 0xff); 91 X[xOff] = n; 92 93 if (++xOff == 16) 94 { 95 processBlock(); 96 } 97 } 98 processLength( long bitLength)99 protected void processLength( 100 long bitLength) 101 { 102 if (xOff > 14) 103 { 104 processBlock(); 105 } 106 107 X[14] = (int)(bitLength >>> 32); 108 X[15] = (int)(bitLength & 0xffffffff); 109 } 110 doFinal( byte[] out, int outOff)111 public int doFinal( 112 byte[] out, 113 int outOff) 114 { 115 finish(); 116 117 Pack.intToBigEndian(H1, out, outOff); 118 Pack.intToBigEndian(H2, out, outOff + 4); 119 Pack.intToBigEndian(H3, out, outOff + 8); 120 Pack.intToBigEndian(H4, out, outOff + 12); 121 Pack.intToBigEndian(H5, out, outOff + 16); 122 123 reset(); 124 125 return DIGEST_LENGTH; 126 } 127 128 /** 129 * reset the chaining variables 130 */ reset()131 public void reset() 132 { 133 super.reset(); 134 135 H1 = 0x67452301; 136 H2 = 0xefcdab89; 137 H3 = 0x98badcfe; 138 H4 = 0x10325476; 139 H5 = 0xc3d2e1f0; 140 141 xOff = 0; 142 for (int i = 0; i != X.length; i++) 143 { 144 X[i] = 0; 145 } 146 } 147 148 // 149 // Additive constants 150 // 151 private static final int Y1 = 0x5a827999; 152 private static final int Y2 = 0x6ed9eba1; 153 private static final int Y3 = 0x8f1bbcdc; 154 private static final int Y4 = 0xca62c1d6; 155 f( int u, int v, int w)156 private int f( 157 int u, 158 int v, 159 int w) 160 { 161 return ((u & v) | ((~u) & w)); 162 } 163 h( int u, int v, int w)164 private int h( 165 int u, 166 int v, 167 int w) 168 { 169 return (u ^ v ^ w); 170 } 171 g( int u, int v, int w)172 private int g( 173 int u, 174 int v, 175 int w) 176 { 177 return ((u & v) | (u & w) | (v & w)); 178 } 179 processBlock()180 protected void processBlock() 181 { 182 // 183 // expand 16 word block into 80 word block. 184 // 185 for (int i = 16; i < 80; i++) 186 { 187 int t = X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16]; 188 X[i] = t << 1 | t >>> 31; 189 } 190 191 // 192 // set up working variables. 193 // 194 int A = H1; 195 int B = H2; 196 int C = H3; 197 int D = H4; 198 int E = H5; 199 200 // 201 // round 1 202 // 203 int idx = 0; 204 205 for (int j = 0; j < 4; j++) 206 { 207 // E = rotateLeft(A, 5) + f(B, C, D) + E + X[idx++] + Y1 208 // B = rotateLeft(B, 30) 209 E += (A << 5 | A >>> 27) + f(B, C, D) + X[idx++] + Y1; 210 B = B << 30 | B >>> 2; 211 212 D += (E << 5 | E >>> 27) + f(A, B, C) + X[idx++] + Y1; 213 A = A << 30 | A >>> 2; 214 215 C += (D << 5 | D >>> 27) + f(E, A, B) + X[idx++] + Y1; 216 E = E << 30 | E >>> 2; 217 218 B += (C << 5 | C >>> 27) + f(D, E, A) + X[idx++] + Y1; 219 D = D << 30 | D >>> 2; 220 221 A += (B << 5 | B >>> 27) + f(C, D, E) + X[idx++] + Y1; 222 C = C << 30 | C >>> 2; 223 } 224 225 // 226 // round 2 227 // 228 for (int j = 0; j < 4; j++) 229 { 230 // E = rotateLeft(A, 5) + h(B, C, D) + E + X[idx++] + Y2 231 // B = rotateLeft(B, 30) 232 E += (A << 5 | A >>> 27) + h(B, C, D) + X[idx++] + Y2; 233 B = B << 30 | B >>> 2; 234 235 D += (E << 5 | E >>> 27) + h(A, B, C) + X[idx++] + Y2; 236 A = A << 30 | A >>> 2; 237 238 C += (D << 5 | D >>> 27) + h(E, A, B) + X[idx++] + Y2; 239 E = E << 30 | E >>> 2; 240 241 B += (C << 5 | C >>> 27) + h(D, E, A) + X[idx++] + Y2; 242 D = D << 30 | D >>> 2; 243 244 A += (B << 5 | B >>> 27) + h(C, D, E) + X[idx++] + Y2; 245 C = C << 30 | C >>> 2; 246 } 247 248 // 249 // round 3 250 // 251 for (int j = 0; j < 4; j++) 252 { 253 // E = rotateLeft(A, 5) + g(B, C, D) + E + X[idx++] + Y3 254 // B = rotateLeft(B, 30) 255 E += (A << 5 | A >>> 27) + g(B, C, D) + X[idx++] + Y3; 256 B = B << 30 | B >>> 2; 257 258 D += (E << 5 | E >>> 27) + g(A, B, C) + X[idx++] + Y3; 259 A = A << 30 | A >>> 2; 260 261 C += (D << 5 | D >>> 27) + g(E, A, B) + X[idx++] + Y3; 262 E = E << 30 | E >>> 2; 263 264 B += (C << 5 | C >>> 27) + g(D, E, A) + X[idx++] + Y3; 265 D = D << 30 | D >>> 2; 266 267 A += (B << 5 | B >>> 27) + g(C, D, E) + X[idx++] + Y3; 268 C = C << 30 | C >>> 2; 269 } 270 271 // 272 // round 4 273 // 274 for (int j = 0; j <= 3; j++) 275 { 276 // E = rotateLeft(A, 5) + h(B, C, D) + E + X[idx++] + Y4 277 // B = rotateLeft(B, 30) 278 E += (A << 5 | A >>> 27) + h(B, C, D) + X[idx++] + Y4; 279 B = B << 30 | B >>> 2; 280 281 D += (E << 5 | E >>> 27) + h(A, B, C) + X[idx++] + Y4; 282 A = A << 30 | A >>> 2; 283 284 C += (D << 5 | D >>> 27) + h(E, A, B) + X[idx++] + Y4; 285 E = E << 30 | E >>> 2; 286 287 B += (C << 5 | C >>> 27) + h(D, E, A) + X[idx++] + Y4; 288 D = D << 30 | D >>> 2; 289 290 A += (B << 5 | B >>> 27) + h(C, D, E) + X[idx++] + Y4; 291 C = C << 30 | C >>> 2; 292 } 293 294 295 H1 += A; 296 H2 += B; 297 H3 += C; 298 H4 += D; 299 H5 += E; 300 301 // 302 // reset start of the buffer. 303 // 304 xOff = 0; 305 for (int i = 0; i < 16; i++) 306 { 307 X[i] = 0; 308 } 309 } 310 copy()311 public Memoable copy() 312 { 313 return new SHA1Digest(this); 314 } 315 reset(Memoable other)316 public void reset(Memoable other) 317 { 318 SHA1Digest d = (SHA1Digest)other; 319 320 super.copyIn(d); 321 copyIn(d); 322 } 323 getEncodedState()324 public byte[] getEncodedState() 325 { 326 byte[] state = new byte[40 + xOff * 4]; 327 328 super.populateState(state); 329 330 Pack.intToBigEndian(H1, state, 16); 331 Pack.intToBigEndian(H2, state, 20); 332 Pack.intToBigEndian(H3, state, 24); 333 Pack.intToBigEndian(H4, state, 28); 334 Pack.intToBigEndian(H5, state, 32); 335 Pack.intToBigEndian(xOff, state, 36); 336 337 for (int i = 0; i != xOff; i++) 338 { 339 Pack.intToBigEndian(X[i], state, 40 + (i * 4)); 340 } 341 342 return state; 343 } 344 } 345 346 347 348 349