1package org.bouncycastle.crypto.digests; 2 3import org.bouncycastle.crypto.ExtendedDigest; 4import org.bouncycastle.crypto.util.Pack; 5 6/** 7 * Base class for SHA-384 and SHA-512. 8 */ 9public abstract class LongDigest 10 implements ExtendedDigest 11{ 12 private static final int BYTE_LENGTH = 128; 13 14 private byte[] xBuf; 15 private int xBufOff; 16 17 private long byteCount1; 18 private long byteCount2; 19 20 protected long H1, H2, H3, H4, H5, H6, H7, H8; 21 22 private long[] W = new long[80]; 23 private int wOff; 24 25 /** 26 * Constructor for variable length word 27 */ 28 protected LongDigest() 29 { 30 xBuf = new byte[8]; 31 xBufOff = 0; 32 33 reset(); 34 } 35 36 /** 37 * Copy constructor. We are using copy constructors in place 38 * of the Object.clone() interface as this interface is not 39 * supported by J2ME. 40 */ 41 protected LongDigest(LongDigest t) 42 { 43 xBuf = new byte[t.xBuf.length]; 44 System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length); 45 46 xBufOff = t.xBufOff; 47 byteCount1 = t.byteCount1; 48 byteCount2 = t.byteCount2; 49 50 H1 = t.H1; 51 H2 = t.H2; 52 H3 = t.H3; 53 H4 = t.H4; 54 H5 = t.H5; 55 H6 = t.H6; 56 H7 = t.H7; 57 H8 = t.H8; 58 59 System.arraycopy(t.W, 0, W, 0, t.W.length); 60 wOff = t.wOff; 61 } 62 63 public void update( 64 byte in) 65 { 66 xBuf[xBufOff++] = in; 67 68 if (xBufOff == xBuf.length) 69 { 70 processWord(xBuf, 0); 71 xBufOff = 0; 72 } 73 74 byteCount1++; 75 } 76 77 public void update( 78 byte[] in, 79 int inOff, 80 int len) 81 { 82 // 83 // fill the current word 84 // 85 while ((xBufOff != 0) && (len > 0)) 86 { 87 update(in[inOff]); 88 89 inOff++; 90 len--; 91 } 92 93 // 94 // process whole words. 95 // 96 while (len > xBuf.length) 97 { 98 processWord(in, inOff); 99 100 inOff += xBuf.length; 101 len -= xBuf.length; 102 byteCount1 += xBuf.length; 103 } 104 105 // 106 // load in the remainder. 107 // 108 while (len > 0) 109 { 110 update(in[inOff]); 111 112 inOff++; 113 len--; 114 } 115 } 116 117 public void finish() 118 { 119 adjustByteCounts(); 120 121 long lowBitLength = byteCount1 << 3; 122 long hiBitLength = byteCount2; 123 124 // 125 // add the pad bytes. 126 // 127 update((byte)128); 128 129 while (xBufOff != 0) 130 { 131 update((byte)0); 132 } 133 134 processLength(lowBitLength, hiBitLength); 135 136 processBlock(); 137 } 138 139 public void reset() 140 { 141 byteCount1 = 0; 142 byteCount2 = 0; 143 144 xBufOff = 0; 145 for (int i = 0; i < xBuf.length; i++) 146 { 147 xBuf[i] = 0; 148 } 149 150 wOff = 0; 151 for (int i = 0; i != W.length; i++) 152 { 153 W[i] = 0; 154 } 155 } 156 157 public int getByteLength() 158 { 159 return BYTE_LENGTH; 160 } 161 162 protected void processWord( 163 byte[] in, 164 int inOff) 165 { 166 W[wOff] = Pack.bigEndianToLong(in, inOff); 167 168 if (++wOff == 16) 169 { 170 processBlock(); 171 } 172 } 173 174 /** 175 * adjust the byte counts so that byteCount2 represents the 176 * upper long (less 3 bits) word of the byte count. 177 */ 178 private void adjustByteCounts() 179 { 180 if (byteCount1 > 0x1fffffffffffffffL) 181 { 182 byteCount2 += (byteCount1 >>> 61); 183 byteCount1 &= 0x1fffffffffffffffL; 184 } 185 } 186 187 protected void processLength( 188 long lowW, 189 long hiW) 190 { 191 if (wOff > 14) 192 { 193 processBlock(); 194 } 195 196 W[14] = hiW; 197 W[15] = lowW; 198 } 199 200 protected void processBlock() 201 { 202 adjustByteCounts(); 203 204 // 205 // expand 16 word block into 80 word blocks. 206 // 207 for (int t = 16; t <= 79; t++) 208 { 209 W[t] = Sigma1(W[t - 2]) + W[t - 7] + Sigma0(W[t - 15]) + W[t - 16]; 210 } 211 212 // 213 // set up working variables. 214 // 215 long a = H1; 216 long b = H2; 217 long c = H3; 218 long d = H4; 219 long e = H5; 220 long f = H6; 221 long g = H7; 222 long h = H8; 223 224 int t = 0; 225 for(int i = 0; i < 10; i ++) 226 { 227 // t = 8 * i 228 h += Sum1(e) + Ch(e, f, g) + K[t] + W[t++]; 229 d += h; 230 h += Sum0(a) + Maj(a, b, c); 231 232 // t = 8 * i + 1 233 g += Sum1(d) + Ch(d, e, f) + K[t] + W[t++]; 234 c += g; 235 g += Sum0(h) + Maj(h, a, b); 236 237 // t = 8 * i + 2 238 f += Sum1(c) + Ch(c, d, e) + K[t] + W[t++]; 239 b += f; 240 f += Sum0(g) + Maj(g, h, a); 241 242 // t = 8 * i + 3 243 e += Sum1(b) + Ch(b, c, d) + K[t] + W[t++]; 244 a += e; 245 e += Sum0(f) + Maj(f, g, h); 246 247 // t = 8 * i + 4 248 d += Sum1(a) + Ch(a, b, c) + K[t] + W[t++]; 249 h += d; 250 d += Sum0(e) + Maj(e, f, g); 251 252 // t = 8 * i + 5 253 c += Sum1(h) + Ch(h, a, b) + K[t] + W[t++]; 254 g += c; 255 c += Sum0(d) + Maj(d, e, f); 256 257 // t = 8 * i + 6 258 b += Sum1(g) + Ch(g, h, a) + K[t] + W[t++]; 259 f += b; 260 b += Sum0(c) + Maj(c, d, e); 261 262 // t = 8 * i + 7 263 a += Sum1(f) + Ch(f, g, h) + K[t] + W[t++]; 264 e += a; 265 a += Sum0(b) + Maj(b, c, d); 266 } 267 268 H1 += a; 269 H2 += b; 270 H3 += c; 271 H4 += d; 272 H5 += e; 273 H6 += f; 274 H7 += g; 275 H8 += h; 276 277 // 278 // reset the offset and clean out the word buffer. 279 // 280 wOff = 0; 281 for (int i = 0; i < 16; i++) 282 { 283 W[i] = 0; 284 } 285 } 286 287 /* SHA-384 and SHA-512 functions (as for SHA-256 but for longs) */ 288 private long Ch( 289 long x, 290 long y, 291 long z) 292 { 293 return ((x & y) ^ ((~x) & z)); 294 } 295 296 private long Maj( 297 long x, 298 long y, 299 long z) 300 { 301 return ((x & y) ^ (x & z) ^ (y & z)); 302 } 303 304 private long Sum0( 305 long x) 306 { 307 return ((x << 36)|(x >>> 28)) ^ ((x << 30)|(x >>> 34)) ^ ((x << 25)|(x >>> 39)); 308 } 309 310 private long Sum1( 311 long x) 312 { 313 return ((x << 50)|(x >>> 14)) ^ ((x << 46)|(x >>> 18)) ^ ((x << 23)|(x >>> 41)); 314 } 315 316 private long Sigma0( 317 long x) 318 { 319 return ((x << 63)|(x >>> 1)) ^ ((x << 56)|(x >>> 8)) ^ (x >>> 7); 320 } 321 322 private long Sigma1( 323 long x) 324 { 325 return ((x << 45)|(x >>> 19)) ^ ((x << 3)|(x >>> 61)) ^ (x >>> 6); 326 } 327 328 /* SHA-384 and SHA-512 Constants 329 * (represent the first 64 bits of the fractional parts of the 330 * cube roots of the first sixty-four prime numbers) 331 */ 332 static final long K[] = { 3330x428a2f98d728ae22L, 0x7137449123ef65cdL, 0xb5c0fbcfec4d3b2fL, 0xe9b5dba58189dbbcL, 3340x3956c25bf348b538L, 0x59f111f1b605d019L, 0x923f82a4af194f9bL, 0xab1c5ed5da6d8118L, 3350xd807aa98a3030242L, 0x12835b0145706fbeL, 0x243185be4ee4b28cL, 0x550c7dc3d5ffb4e2L, 3360x72be5d74f27b896fL, 0x80deb1fe3b1696b1L, 0x9bdc06a725c71235L, 0xc19bf174cf692694L, 3370xe49b69c19ef14ad2L, 0xefbe4786384f25e3L, 0x0fc19dc68b8cd5b5L, 0x240ca1cc77ac9c65L, 3380x2de92c6f592b0275L, 0x4a7484aa6ea6e483L, 0x5cb0a9dcbd41fbd4L, 0x76f988da831153b5L, 3390x983e5152ee66dfabL, 0xa831c66d2db43210L, 0xb00327c898fb213fL, 0xbf597fc7beef0ee4L, 3400xc6e00bf33da88fc2L, 0xd5a79147930aa725L, 0x06ca6351e003826fL, 0x142929670a0e6e70L, 3410x27b70a8546d22ffcL, 0x2e1b21385c26c926L, 0x4d2c6dfc5ac42aedL, 0x53380d139d95b3dfL, 3420x650a73548baf63deL, 0x766a0abb3c77b2a8L, 0x81c2c92e47edaee6L, 0x92722c851482353bL, 3430xa2bfe8a14cf10364L, 0xa81a664bbc423001L, 0xc24b8b70d0f89791L, 0xc76c51a30654be30L, 3440xd192e819d6ef5218L, 0xd69906245565a910L, 0xf40e35855771202aL, 0x106aa07032bbd1b8L, 3450x19a4c116b8d2d0c8L, 0x1e376c085141ab53L, 0x2748774cdf8eeb99L, 0x34b0bcb5e19b48a8L, 3460x391c0cb3c5c95a63L, 0x4ed8aa4ae3418acbL, 0x5b9cca4f7763e373L, 0x682e6ff3d6b2b8a3L, 3470x748f82ee5defb2fcL, 0x78a5636f43172f60L, 0x84c87814a1f0ab72L, 0x8cc702081a6439ecL, 3480x90befffa23631e28L, 0xa4506cebde82bde9L, 0xbef9a3f7b2c67915L, 0xc67178f2e372532bL, 3490xca273eceea26619cL, 0xd186b8c721c0c207L, 0xeada7dd6cde0eb1eL, 0xf57d4f7fee6ed178L, 3500x06f067aa72176fbaL, 0x0a637dc5a2c898a6L, 0x113f9804bef90daeL, 0x1b710b35131c471bL, 3510x28db77f523047d84L, 0x32caab7b40c72493L, 0x3c9ebe0a15c9bebcL, 0x431d67c49c100d4cL, 3520x4cc5d4becb3e42b6L, 0x597f299cfc657e2aL, 0x5fcb6fab3ad6faecL, 0x6c44198c4a475817L 353 }; 354} 355