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