SHA224Digest.java revision 2ad60cfc28e14ee8f0bb038720836a4696c478ad
1package org.bouncycastle.crypto.digests; 2 3 4import org.bouncycastle.crypto.digests.GeneralDigest; 5 6 7/** 8 * SHA-224 as described in RFC 3874 9 * <pre> 10 * block word digest 11 * SHA-1 512 32 160 12 * SHA-224 512 32 224 13 * SHA-256 512 32 256 14 * SHA-384 1024 64 384 15 * SHA-512 1024 64 512 16 * </pre> 17 */ 18public class SHA224Digest 19 extends GeneralDigest 20{ 21 private static final int DIGEST_LENGTH = 28; 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 SHA224Digest() 32 { 33 reset(); 34 } 35 36 /** 37 * Copy constructor. This will copy the state of the provided 38 * message digest. 39 */ 40 public SHA224Digest(SHA224Digest 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-224"; 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 117 reset(); 118 119 return DIGEST_LENGTH; 120 } 121 122 /** 123 * reset the chaining variables 124 */ 125 public void reset() 126 { 127 super.reset(); 128 129 /* SHA-224 initial hash value 130 */ 131 132 H1 = 0xc1059ed8; 133 H2 = 0x367cd507; 134 H3 = 0x3070dd17; 135 H4 = 0xf70e5939; 136 H5 = 0xffc00b31; 137 H6 = 0x68581511; 138 H7 = 0x64f98fa7; 139 H8 = 0xbefa4fa4; 140 141 xOff = 0; 142 for (int i = 0; i != X.length; i++) 143 { 144 X[i] = 0; 145 } 146 } 147 148 protected void processBlock() 149 { 150 // 151 // expand 16 word block into 64 word blocks. 152 // 153 for (int t = 16; t <= 63; t++) 154 { 155 X[t] = Theta1(X[t - 2]) + X[t - 7] + Theta0(X[t - 15]) + X[t - 16]; 156 } 157 158 // 159 // set up working variables. 160 // 161 int a = H1; 162 int b = H2; 163 int c = H3; 164 int d = H4; 165 int e = H5; 166 int f = H6; 167 int g = H7; 168 int h = H8; 169 170 171 int t = 0; 172 for(int i = 0; i < 8; i ++) 173 { 174 // t = 8 * i 175 h += Sum1(e) + Ch(e, f, g) + K[t] + X[t++]; 176 d += h; 177 h += Sum0(a) + Maj(a, b, c); 178 179 // t = 8 * i + 1 180 g += Sum1(d) + Ch(d, e, f) + K[t] + X[t++]; 181 c += g; 182 g += Sum0(h) + Maj(h, a, b); 183 184 // t = 8 * i + 2 185 f += Sum1(c) + Ch(c, d, e) + K[t] + X[t++]; 186 b += f; 187 f += Sum0(g) + Maj(g, h, a); 188 189 // t = 8 * i + 3 190 e += Sum1(b) + Ch(b, c, d) + K[t] + X[t++]; 191 a += e; 192 e += Sum0(f) + Maj(f, g, h); 193 194 // t = 8 * i + 4 195 d += Sum1(a) + Ch(a, b, c) + K[t] + X[t++]; 196 h += d; 197 d += Sum0(e) + Maj(e, f, g); 198 199 // t = 8 * i + 5 200 c += Sum1(h) + Ch(h, a, b) + K[t] + X[t++]; 201 g += c; 202 c += Sum0(d) + Maj(d, e, f); 203 204 // t = 8 * i + 6 205 b += Sum1(g) + Ch(g, h, a) + K[t] + X[t++]; 206 f += b; 207 b += Sum0(c) + Maj(c, d, e); 208 209 // t = 8 * i + 7 210 a += Sum1(f) + Ch(f, g, h) + K[t] + X[t++]; 211 e += a; 212 a += Sum0(b) + Maj(b, c, d); 213 } 214 215 H1 += a; 216 H2 += b; 217 H3 += c; 218 H4 += d; 219 H5 += e; 220 H6 += f; 221 H7 += g; 222 H8 += h; 223 224 // 225 // reset the offset and clean out the word buffer. 226 // 227 xOff = 0; 228 for (int i = 0; i < 16; i++) 229 { 230 X[i] = 0; 231 } 232 } 233 234 /* SHA-224 functions */ 235 private int Ch( 236 int x, 237 int y, 238 int z) 239 { 240 return ((x & y) ^ ((~x) & z)); 241 } 242 243 private int Maj( 244 int x, 245 int y, 246 int z) 247 { 248 return ((x & y) ^ (x & z) ^ (y & z)); 249 } 250 251 private int Sum0( 252 int x) 253 { 254 return ((x >>> 2) | (x << 30)) ^ ((x >>> 13) | (x << 19)) ^ ((x >>> 22) | (x << 10)); 255 } 256 257 private int Sum1( 258 int x) 259 { 260 return ((x >>> 6) | (x << 26)) ^ ((x >>> 11) | (x << 21)) ^ ((x >>> 25) | (x << 7)); 261 } 262 263 private int Theta0( 264 int x) 265 { 266 return ((x >>> 7) | (x << 25)) ^ ((x >>> 18) | (x << 14)) ^ (x >>> 3); 267 } 268 269 private int Theta1( 270 int x) 271 { 272 return ((x >>> 17) | (x << 15)) ^ ((x >>> 19) | (x << 13)) ^ (x >>> 10); 273 } 274 275 /* SHA-224 Constants 276 * (represent the first 32 bits of the fractional parts of the 277 * cube roots of the first sixty-four prime numbers) 278 */ 279 static final int K[] = { 280 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 281 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 282 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 283 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 284 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 285 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 286 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 287 }; 288} 289 290