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 protected ulong H1, H2, H3, H4, H5, H6, H7, H8;
31 private ulong[] W = new ulong [80];
34 public SHA384Managed ()
41 public override void Initialize ()
43 // SHA-384 initial hash value
44 // The first 64 bits of the fractional parts of the square roots
45 // of the 9th through 16th prime numbers
46 H1 = 0xcbbb9d5dc1059ed8L;
47 H2 = 0x629a292a367cd507L;
48 H3 = 0x9159015a3070dd17L;
49 H4 = 0x152fecd8f70e5939L;
50 H5 = 0x67332667ffc00b31L;
51 H6 = 0x8eb44a8768581511L;
52 H7 = 0xdb0c2e0d64f98fa7L;
53 H8 = 0x47b5481dbefa4fa4L;
59 for (int i = 0; i < xBuf.Length; i++)
63 for (int i = 0; i != W.Length; i++)
69 protected override void HashCore (byte[] rgb, int start, int count)
71 // fill the current word
72 while ((xBufOff != 0) && (count > 0)) {
78 // process whole words.
79 while (count > xBuf.Length) {
80 processWord(rgb, start);
83 byteCount1 += (ulong) xBuf.Length;
86 // load in the remainder.
94 protected override byte[] HashFinal ()
98 ulong lowBitLength = byteCount1 << 3;
99 ulong hiBitLength = byteCount2;
101 // add the pad bytes.
102 update ( (byte) 128);
106 processLength (lowBitLength, hiBitLength);
109 byte[] output = new byte [48];
110 unpackWord(H1, output, 0);
111 unpackWord(H2, output, 8);
112 unpackWord(H3, output, 16);
113 unpackWord(H4, output, 24);
114 unpackWord(H5, output, 32);
115 unpackWord(H6, output, 40);
121 private void update (byte input)
123 xBuf [xBufOff++] = input;
124 if (xBufOff == xBuf.Length) {
125 processWord(xBuf, 0);
131 private void processWord (byte[] input, int inOff)
133 W [wOff++] = ( (ulong) (input [inOff] & 0xff) << 56)
134 | ( (ulong) (input [inOff + 1] & 0xff) << 48)
135 | ( (ulong) (input [inOff + 2] & 0xff) << 40)
136 | ( (ulong) (input [inOff + 3] & 0xff) << 32)
137 | ( (ulong) (input [inOff + 4] & 0xff) << 24)
138 | ( (ulong) (input [inOff + 5] & 0xff) << 16)
139 | ( (ulong) (input [inOff + 6] & 0xff) << 8)
140 | ( (ulong) (input [inOff + 7] & 0xff));
145 private void unpackWord (ulong word, byte[] output, int outOff)
147 output[outOff] = (byte) (word >> 56);
148 output[outOff + 1] = (byte) (word >> 48);
149 output[outOff + 2] = (byte) (word >> 40);
150 output[outOff + 3] = (byte) (word >> 32);
151 output[outOff + 4] = (byte) (word >> 24);
152 output[outOff + 5] = (byte) (word >> 16);
153 output[outOff + 6] = (byte) (word >> 8);
154 output[outOff + 7] = (byte) word;
157 // adjust the byte counts so that byteCount2 represents the
158 // upper long (less 3 bits) word of the byte count.
159 private void adjustByteCounts()
161 if (byteCount1 > 0x1fffffffffffffffL) {
162 byteCount2 += (byteCount1 >> 61);
163 byteCount1 &= 0x1fffffffffffffffL;
167 private void processLength (ulong lowW, ulong hiW)
175 private void processBlock ()
178 // expand 16 word block into 80 word blocks.
179 for (int t = 16; t <= 79; t++)
180 W[t] = Sigma1 (W [t - 2]) + W [t - 7] + Sigma0 (W [t - 15]) + W [t - 16];
182 // set up working variables.
192 for (int t = 0; t <= 79; t++) {
193 ulong T1 = h + Sum1 (e) + Ch (e, f, g) + K [t] + W [t];
194 ulong T2 = Sum0 (a) + Maj (a, b, c);
213 // reset the offset and clean out the word buffer.
215 for (int i = 0; i != W.Length; i++)
219 private ulong rotateRight (ulong x, int n)
221 return (x >> n) | (x << (64 - n));
224 /* SHA-384 and SHA-512 functions (as for SHA-256 but for longs) */
225 private ulong Ch (ulong x, ulong y, ulong z)
227 return ((x & y) ^ ((~x) & z));
230 private ulong Maj (ulong x, ulong y, ulong z)
232 return ((x & y) ^ (x & z) ^ (y & z));
235 private ulong Sum0 (ulong x)
237 return rotateRight (x, 28) ^ rotateRight (x, 34) ^ rotateRight (x, 39);
240 private ulong Sum1 (ulong x)
242 return rotateRight (x, 14) ^ rotateRight (x, 18) ^ rotateRight (x, 41);
245 private ulong Sigma0 (ulong x)
247 return rotateRight (x, 1) ^ rotateRight(x, 8) ^ (x >> 7);
250 private ulong Sigma1 (ulong x)
252 return rotateRight (x, 19) ^ rotateRight (x, 61) ^ (x >> 6);
255 // SHA-384 and SHA-512 Constants
256 // Rrepresent the first 64 bits of the fractional parts of the
257 // cube roots of the first sixty-four prime numbers
259 0x428a2f98d728ae22L, 0x7137449123ef65cdL, 0xb5c0fbcfec4d3b2fL, 0xe9b5dba58189dbbcL,
260 0x3956c25bf348b538L, 0x59f111f1b605d019L, 0x923f82a4af194f9bL, 0xab1c5ed5da6d8118L,
261 0xd807aa98a3030242L, 0x12835b0145706fbeL, 0x243185be4ee4b28cL, 0x550c7dc3d5ffb4e2L,
262 0x72be5d74f27b896fL, 0x80deb1fe3b1696b1L, 0x9bdc06a725c71235L, 0xc19bf174cf692694L,
263 0xe49b69c19ef14ad2L, 0xefbe4786384f25e3L, 0x0fc19dc68b8cd5b5L, 0x240ca1cc77ac9c65L,
264 0x2de92c6f592b0275L, 0x4a7484aa6ea6e483L, 0x5cb0a9dcbd41fbd4L, 0x76f988da831153b5L,
265 0x983e5152ee66dfabL, 0xa831c66d2db43210L, 0xb00327c898fb213fL, 0xbf597fc7beef0ee4L,
266 0xc6e00bf33da88fc2L, 0xd5a79147930aa725L, 0x06ca6351e003826fL, 0x142929670a0e6e70L,
267 0x27b70a8546d22ffcL, 0x2e1b21385c26c926L, 0x4d2c6dfc5ac42aedL, 0x53380d139d95b3dfL,
268 0x650a73548baf63deL, 0x766a0abb3c77b2a8L, 0x81c2c92e47edaee6L, 0x92722c851482353bL,
269 0xa2bfe8a14cf10364L, 0xa81a664bbc423001L, 0xc24b8b70d0f89791L, 0xc76c51a30654be30L,
270 0xd192e819d6ef5218L, 0xd69906245565a910L, 0xf40e35855771202aL, 0x106aa07032bbd1b8L,
271 0x19a4c116b8d2d0c8L, 0x1e376c085141ab53L, 0x2748774cdf8eeb99L, 0x34b0bcb5e19b48a8L,
272 0x391c0cb3c5c95a63L, 0x4ed8aa4ae3418acbL, 0x5b9cca4f7763e373L, 0x682e6ff3d6b2b8a3L,
273 0x748f82ee5defb2fcL, 0x78a5636f43172f60L, 0x84c87814a1f0ab72L, 0x8cc702081a6439ecL,
274 0x90befffa23631e28L, 0xa4506cebde82bde9L, 0xbef9a3f7b2c67915L, 0xc67178f2e372532bL,
275 0xca273eceea26619cL, 0xd186b8c721c0c207L, 0xeada7dd6cde0eb1eL, 0xf57d4f7fee6ed178L,
276 0x06f067aa72176fbaL, 0x0a637dc5a2c898a6L, 0x113f9804bef90daeL, 0x1b710b35131c471bL,
277 0x28db77f523047d84L, 0x32caab7b40c72493L, 0x3c9ebe0a15c9bebcL, 0x431d67c49c100d4cL,
278 0x4cc5d4becb3e42b6L, 0x597f299cfc657e2aL, 0x5fcb6fab3ad6faecL, 0x6c44198c4a475817L