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