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