2 // System.Security.Cryptography.SHA384Managed.cs
5 // Dan Lewis (dihlewis@yahoo.co.uk)
6 // Sébastien Pouliot (spouliot@motus.com)
9 // Implementation translated from Bouncy Castle JCE (http://www.bouncycastle.org/)
10 // See bouncycastle.txt for license.
15 namespace System.Security.Cryptography {
17 public class SHA384Managed : SHA384 {
23 private ulong byteCount1;
25 private ulong byteCount2;
28 private ulong H1, H2, H3, H4, H5, H6, H7, H8;
30 private ulong[] W = new ulong [80];
33 public SHA384Managed ()
40 public override void Initialize ()
42 // SHA-384 initial hash value
43 // The first 64 bits of the fractional parts of the square roots
44 // of the 9th through 16th prime numbers
45 H1 = 0xcbbb9d5dc1059ed8L;
46 H2 = 0x629a292a367cd507L;
47 H3 = 0x9159015a3070dd17L;
48 H4 = 0x152fecd8f70e5939L;
49 H5 = 0x67332667ffc00b31L;
50 H6 = 0x8eb44a8768581511L;
51 H7 = 0xdb0c2e0d64f98fa7L;
52 H8 = 0x47b5481dbefa4fa4L;
58 for (int i = 0; i < xBuf.Length; i++)
62 for (int i = 0; i != W.Length; i++)
68 protected override void HashCore (byte[] rgb, int start, int count)
70 // fill the current word
71 while ((xBufOff != 0) && (count > 0)) {
77 // process whole words.
78 while (count > xBuf.Length) {
79 processWord(rgb, start);
82 byteCount1 += (ulong) xBuf.Length;
85 // load in the remainder.
93 protected override byte[] HashFinal ()
97 ulong lowBitLength = byteCount1 << 3;
98 ulong hiBitLength = byteCount2;
100 // add the pad bytes.
101 update ( (byte) 128);
105 processLength (lowBitLength, hiBitLength);
108 byte[] output = new byte [48];
109 unpackWord(H1, output, 0);
110 unpackWord(H2, output, 8);
111 unpackWord(H3, output, 16);
112 unpackWord(H4, output, 24);
113 unpackWord(H5, output, 32);
114 unpackWord(H6, output, 40);
120 private void update (byte input)
122 xBuf [xBufOff++] = input;
123 if (xBufOff == xBuf.Length) {
124 processWord(xBuf, 0);
130 private void processWord (byte[] input, int inOff)
132 W [wOff++] = ( (ulong) input [inOff] << 56)
133 | ( (ulong) input [inOff + 1] << 48)
134 | ( (ulong) input [inOff + 2] << 40)
135 | ( (ulong) input [inOff + 3] << 32)
136 | ( (ulong) input [inOff + 4] << 24)
137 | ( (ulong) input [inOff + 5] << 16)
138 | ( (ulong) input [inOff + 6] << 8)
139 | ( (ulong) input [inOff + 7]);
144 private void unpackWord (ulong word, byte[] output, int outOff)
146 output[outOff] = (byte) (word >> 56);
147 output[outOff + 1] = (byte) (word >> 48);
148 output[outOff + 2] = (byte) (word >> 40);
149 output[outOff + 3] = (byte) (word >> 32);
150 output[outOff + 4] = (byte) (word >> 24);
151 output[outOff + 5] = (byte) (word >> 16);
152 output[outOff + 6] = (byte) (word >> 8);
153 output[outOff + 7] = (byte) word;
156 // adjust the byte counts so that byteCount2 represents the
157 // upper long (less 3 bits) word of the byte count.
158 private void adjustByteCounts()
160 if (byteCount1 > 0x1fffffffffffffffL) {
161 byteCount2 += (byteCount1 >> 61);
162 byteCount1 &= 0x1fffffffffffffffL;
166 private void processLength (ulong lowW, ulong hiW)
174 private void processBlock ()
177 // expand 16 word block into 80 word blocks.
178 for (int t = 16; t <= 79; t++)
179 W[t] = Sigma1 (W [t - 2]) + W [t - 7] + Sigma0 (W [t - 15]) + W [t - 16];
181 // set up working variables.
191 for (int t = 0; t <= 79; t++) {
192 ulong T1 = h + Sum1 (e) + Ch (e, f, g) + K [t] + W [t];
193 ulong T2 = Sum0 (a) + Maj (a, b, c);
212 // reset the offset and clean out the word buffer.
214 for (int i = 0; i != W.Length; i++)
218 private ulong rotateRight (ulong x, int n)
220 return (x >> n) | (x << (64 - n));
223 /* SHA-384 and SHA-512 functions (as for SHA-256 but for longs) */
224 private ulong Ch (ulong x, ulong y, ulong z)
226 return ((x & y) ^ ((~x) & z));
229 private ulong Maj (ulong x, ulong y, ulong z)
231 return ((x & y) ^ (x & z) ^ (y & z));
234 private ulong Sum0 (ulong x)
236 return rotateRight (x, 28) ^ rotateRight (x, 34) ^ rotateRight (x, 39);
239 private ulong Sum1 (ulong x)
241 return rotateRight (x, 14) ^ rotateRight (x, 18) ^ rotateRight (x, 41);
244 private ulong Sigma0 (ulong x)
246 return rotateRight (x, 1) ^ rotateRight(x, 8) ^ (x >> 7);
249 private ulong Sigma1 (ulong x)
251 return rotateRight (x, 19) ^ rotateRight (x, 61) ^ (x >> 6);
254 // SHA-384 and SHA-512 Constants
255 // Rrepresent the first 64 bits of the fractional parts of the
256 // cube roots of the first sixty-four prime numbers
258 0x428a2f98d728ae22L, 0x7137449123ef65cdL, 0xb5c0fbcfec4d3b2fL, 0xe9b5dba58189dbbcL,
259 0x3956c25bf348b538L, 0x59f111f1b605d019L, 0x923f82a4af194f9bL, 0xab1c5ed5da6d8118L,
260 0xd807aa98a3030242L, 0x12835b0145706fbeL, 0x243185be4ee4b28cL, 0x550c7dc3d5ffb4e2L,
261 0x72be5d74f27b896fL, 0x80deb1fe3b1696b1L, 0x9bdc06a725c71235L, 0xc19bf174cf692694L,
262 0xe49b69c19ef14ad2L, 0xefbe4786384f25e3L, 0x0fc19dc68b8cd5b5L, 0x240ca1cc77ac9c65L,
263 0x2de92c6f592b0275L, 0x4a7484aa6ea6e483L, 0x5cb0a9dcbd41fbd4L, 0x76f988da831153b5L,
264 0x983e5152ee66dfabL, 0xa831c66d2db43210L, 0xb00327c898fb213fL, 0xbf597fc7beef0ee4L,
265 0xc6e00bf33da88fc2L, 0xd5a79147930aa725L, 0x06ca6351e003826fL, 0x142929670a0e6e70L,
266 0x27b70a8546d22ffcL, 0x2e1b21385c26c926L, 0x4d2c6dfc5ac42aedL, 0x53380d139d95b3dfL,
267 0x650a73548baf63deL, 0x766a0abb3c77b2a8L, 0x81c2c92e47edaee6L, 0x92722c851482353bL,
268 0xa2bfe8a14cf10364L, 0xa81a664bbc423001L, 0xc24b8b70d0f89791L, 0xc76c51a30654be30L,
269 0xd192e819d6ef5218L, 0xd69906245565a910L, 0xf40e35855771202aL, 0x106aa07032bbd1b8L,
270 0x19a4c116b8d2d0c8L, 0x1e376c085141ab53L, 0x2748774cdf8eeb99L, 0x34b0bcb5e19b48a8L,
271 0x391c0cb3c5c95a63L, 0x4ed8aa4ae3418acbL, 0x5b9cca4f7763e373L, 0x682e6ff3d6b2b8a3L,
272 0x748f82ee5defb2fcL, 0x78a5636f43172f60L, 0x84c87814a1f0ab72L, 0x8cc702081a6439ecL,
273 0x90befffa23631e28L, 0xa4506cebde82bde9L, 0xbef9a3f7b2c67915L, 0xc67178f2e372532bL,
274 0xca273eceea26619cL, 0xd186b8c721c0c207L, 0xeada7dd6cde0eb1eL, 0xf57d4f7fee6ed178L,
275 0x06f067aa72176fbaL, 0x0a637dc5a2c898a6L, 0x113f9804bef90daeL, 0x1b710b35131c471bL,
276 0x28db77f523047d84L, 0x32caab7b40c72493L, 0x3c9ebe0a15c9bebcL, 0x431d67c49c100d4cL,
277 0x4cc5d4becb3e42b6L, 0x597f299cfc657e2aL, 0x5fcb6fab3ad6faecL, 0x6c44198c4a475817L