1 package org.bouncycastle.crypto.digests; 2 3 4 import org.bouncycastle.util.Memoable; 5 import org.bouncycastle.util.Pack; 6 7 8 /** 9 * FIPS 180-2 implementation of SHA-256. 10 * 11 * <pre> 12 * block word digest 13 * SHA-1 512 32 160 14 * SHA-256 512 32 256 15 * SHA-384 1024 64 384 16 * SHA-512 1024 64 512 17 * </pre> 18 */ 19 public class SHA256Digest 20 extends GeneralDigest 21 implements EncodableDigest 22 { 23 private static final int DIGEST_LENGTH = 32; 24 25 private int H1, H2, H3, H4, H5, H6, H7, H8; 26 27 private int[] X = new int[64]; 28 private int xOff; 29 30 /** 31 * Standard constructor 32 */ SHA256Digest()33 public SHA256Digest() 34 { 35 reset(); 36 } 37 38 /** 39 * Copy constructor. This will copy the state of the provided 40 * message digest. 41 */ SHA256Digest(SHA256Digest t)42 public SHA256Digest(SHA256Digest t) 43 { 44 super(t); 45 46 copyIn(t); 47 } 48 copyIn(SHA256Digest t)49 private void copyIn(SHA256Digest t) 50 { 51 super.copyIn(t); 52 53 H1 = t.H1; 54 H2 = t.H2; 55 H3 = t.H3; 56 H4 = t.H4; 57 H5 = t.H5; 58 H6 = t.H6; 59 H7 = t.H7; 60 H8 = t.H8; 61 62 System.arraycopy(t.X, 0, X, 0, t.X.length); 63 xOff = t.xOff; 64 } 65 66 /** 67 * State constructor - create a digest initialised with the state of a previous one. 68 * 69 * @param encodedState the encoded state from the originating digest. 70 */ SHA256Digest(byte[] encodedState)71 public SHA256Digest(byte[] encodedState) 72 { 73 super(encodedState); 74 75 H1 = Pack.bigEndianToInt(encodedState, 16); 76 H2 = Pack.bigEndianToInt(encodedState, 20); 77 H3 = Pack.bigEndianToInt(encodedState, 24); 78 H4 = Pack.bigEndianToInt(encodedState, 28); 79 H5 = Pack.bigEndianToInt(encodedState, 32); 80 H6 = Pack.bigEndianToInt(encodedState, 36); 81 H7 = Pack.bigEndianToInt(encodedState, 40); 82 H8 = Pack.bigEndianToInt(encodedState, 44); 83 84 xOff = Pack.bigEndianToInt(encodedState, 48); 85 for (int i = 0; i != xOff; i++) 86 { 87 X[i] = Pack.bigEndianToInt(encodedState, 52 + (i * 4)); 88 } 89 } 90 91 getAlgorithmName()92 public String getAlgorithmName() 93 { 94 return "SHA-256"; 95 } 96 getDigestSize()97 public int getDigestSize() 98 { 99 return DIGEST_LENGTH; 100 } 101 processWord( byte[] in, int inOff)102 protected void processWord( 103 byte[] in, 104 int inOff) 105 { 106 // Note: Inlined for performance 107 // X[xOff] = Pack.bigEndianToInt(in, inOff); 108 int n = in[inOff] << 24; 109 n |= (in[++inOff] & 0xff) << 16; 110 n |= (in[++inOff] & 0xff) << 8; 111 n |= (in[++inOff] & 0xff); 112 X[xOff] = n; 113 114 if (++xOff == 16) 115 { 116 processBlock(); 117 } 118 } 119 processLength( long bitLength)120 protected void processLength( 121 long bitLength) 122 { 123 if (xOff > 14) 124 { 125 processBlock(); 126 } 127 128 X[14] = (int)(bitLength >>> 32); 129 X[15] = (int)(bitLength & 0xffffffff); 130 } 131 doFinal( byte[] out, int outOff)132 public int doFinal( 133 byte[] out, 134 int outOff) 135 { 136 finish(); 137 138 Pack.intToBigEndian(H1, out, outOff); 139 Pack.intToBigEndian(H2, out, outOff + 4); 140 Pack.intToBigEndian(H3, out, outOff + 8); 141 Pack.intToBigEndian(H4, out, outOff + 12); 142 Pack.intToBigEndian(H5, out, outOff + 16); 143 Pack.intToBigEndian(H6, out, outOff + 20); 144 Pack.intToBigEndian(H7, out, outOff + 24); 145 Pack.intToBigEndian(H8, out, outOff + 28); 146 147 reset(); 148 149 return DIGEST_LENGTH; 150 } 151 152 /** 153 * reset the chaining variables 154 */ reset()155 public void reset() 156 { 157 super.reset(); 158 159 /* SHA-256 initial hash value 160 * The first 32 bits of the fractional parts of the square roots 161 * of the first eight prime numbers 162 */ 163 164 H1 = 0x6a09e667; 165 H2 = 0xbb67ae85; 166 H3 = 0x3c6ef372; 167 H4 = 0xa54ff53a; 168 H5 = 0x510e527f; 169 H6 = 0x9b05688c; 170 H7 = 0x1f83d9ab; 171 H8 = 0x5be0cd19; 172 173 xOff = 0; 174 for (int i = 0; i != X.length; i++) 175 { 176 X[i] = 0; 177 } 178 } 179 processBlock()180 protected void processBlock() 181 { 182 // 183 // expand 16 word block into 64 word blocks. 184 // 185 for (int t = 16; t <= 63; t++) 186 { 187 X[t] = Theta1(X[t - 2]) + X[t - 7] + Theta0(X[t - 15]) + X[t - 16]; 188 } 189 190 // 191 // set up working variables. 192 // 193 int a = H1; 194 int b = H2; 195 int c = H3; 196 int d = H4; 197 int e = H5; 198 int f = H6; 199 int g = H7; 200 int h = H8; 201 202 int t = 0; 203 for(int i = 0; i < 8; i ++) 204 { 205 // t = 8 * i 206 h += Sum1(e) + Ch(e, f, g) + K[t] + X[t]; 207 d += h; 208 h += Sum0(a) + Maj(a, b, c); 209 ++t; 210 211 // t = 8 * i + 1 212 g += Sum1(d) + Ch(d, e, f) + K[t] + X[t]; 213 c += g; 214 g += Sum0(h) + Maj(h, a, b); 215 ++t; 216 217 // t = 8 * i + 2 218 f += Sum1(c) + Ch(c, d, e) + K[t] + X[t]; 219 b += f; 220 f += Sum0(g) + Maj(g, h, a); 221 ++t; 222 223 // t = 8 * i + 3 224 e += Sum1(b) + Ch(b, c, d) + K[t] + X[t]; 225 a += e; 226 e += Sum0(f) + Maj(f, g, h); 227 ++t; 228 229 // t = 8 * i + 4 230 d += Sum1(a) + Ch(a, b, c) + K[t] + X[t]; 231 h += d; 232 d += Sum0(e) + Maj(e, f, g); 233 ++t; 234 235 // t = 8 * i + 5 236 c += Sum1(h) + Ch(h, a, b) + K[t] + X[t]; 237 g += c; 238 c += Sum0(d) + Maj(d, e, f); 239 ++t; 240 241 // t = 8 * i + 6 242 b += Sum1(g) + Ch(g, h, a) + K[t] + X[t]; 243 f += b; 244 b += Sum0(c) + Maj(c, d, e); 245 ++t; 246 247 // t = 8 * i + 7 248 a += Sum1(f) + Ch(f, g, h) + K[t] + X[t]; 249 e += a; 250 a += Sum0(b) + Maj(b, c, d); 251 ++t; 252 } 253 254 H1 += a; 255 H2 += b; 256 H3 += c; 257 H4 += d; 258 H5 += e; 259 H6 += f; 260 H7 += g; 261 H8 += h; 262 263 // 264 // reset the offset and clean out the word buffer. 265 // 266 xOff = 0; 267 for (int i = 0; i < 16; i++) 268 { 269 X[i] = 0; 270 } 271 } 272 273 /* SHA-256 functions */ Ch(int x, int y, int z)274 private static int Ch(int x, int y, int z) 275 { 276 return (x & y) ^ ((~x) & z); 277 // return z ^ (x & (y ^ z)); 278 } 279 Maj(int x, int y, int z)280 private static int Maj(int x, int y, int z) 281 { 282 // return (x & y) ^ (x & z) ^ (y & z); 283 return (x & y) | (z & (x ^ y)); 284 } 285 Sum0(int x)286 private static int Sum0(int x) 287 { 288 return ((x >>> 2) | (x << 30)) ^ ((x >>> 13) | (x << 19)) ^ ((x >>> 22) | (x << 10)); 289 } 290 Sum1(int x)291 private static int Sum1(int x) 292 { 293 return ((x >>> 6) | (x << 26)) ^ ((x >>> 11) | (x << 21)) ^ ((x >>> 25) | (x << 7)); 294 } 295 Theta0(int x)296 private static int Theta0(int x) 297 { 298 return ((x >>> 7) | (x << 25)) ^ ((x >>> 18) | (x << 14)) ^ (x >>> 3); 299 } 300 Theta1(int x)301 private static int Theta1(int x) 302 { 303 return ((x >>> 17) | (x << 15)) ^ ((x >>> 19) | (x << 13)) ^ (x >>> 10); 304 } 305 306 /* SHA-256 Constants 307 * (represent the first 32 bits of the fractional parts of the 308 * cube roots of the first sixty-four prime numbers) 309 */ 310 static final int K[] = { 311 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 312 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 313 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 314 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 315 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 316 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 317 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 318 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 319 }; 320 copy()321 public Memoable copy() 322 { 323 return new SHA256Digest(this); 324 } 325 reset(Memoable other)326 public void reset(Memoable other) 327 { 328 SHA256Digest d = (SHA256Digest)other; 329 330 copyIn(d); 331 } 332 getEncodedState()333 public byte[] getEncodedState() 334 { 335 byte[] state = new byte[52 + xOff * 4]; 336 337 super.populateState(state); 338 339 Pack.intToBigEndian(H1, state, 16); 340 Pack.intToBigEndian(H2, state, 20); 341 Pack.intToBigEndian(H3, state, 24); 342 Pack.intToBigEndian(H4, state, 28); 343 Pack.intToBigEndian(H5, state, 32); 344 Pack.intToBigEndian(H6, state, 36); 345 Pack.intToBigEndian(H7, state, 40); 346 Pack.intToBigEndian(H8, state, 44); 347 Pack.intToBigEndian(xOff, state, 48); 348 349 for (int i = 0; i != xOff; i++) 350 { 351 Pack.intToBigEndian(X[i], state, 52 + (i * 4)); 352 } 353 354 return state; 355 } 356 } 357 358