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