2 // System.Security.Cryptography.SHA384Managed.cs
5 // Dan Lewis (dihlewis@yahoo.co.uk)
6 // Sebastien Pouliot (sebastien@ximian.com)
9 // Implementation translated from Bouncy Castle JCE (http://www.bouncycastle.org/)
10 // See bouncycastle.txt for license.
11 // (C) 2004 Novell (http://www.novell.com)
16 namespace System.Security.Cryptography {
18 public class SHA384Managed : SHA384 {
23 private ulong byteCount1;
24 private ulong byteCount2;
26 private ulong H1, H2, H3, H4, H5, H6, H7, H8;
30 public SHA384Managed ()
34 Initialize (false); // limited initialization
37 private void Initialize (bool reuse)
39 // SHA-384 initial hash value
40 // The first 64 bits of the fractional parts of the square roots
41 // of the 9th through 16th prime numbers
42 H1 = 0xcbbb9d5dc1059ed8L;
43 H2 = 0x629a292a367cd507L;
44 H3 = 0x9159015a3070dd17L;
45 H4 = 0x152fecd8f70e5939L;
46 H5 = 0x67332667ffc00b31L;
47 H6 = 0x8eb44a8768581511L;
48 H7 = 0xdb0c2e0d64f98fa7L;
49 H8 = 0x47b5481dbefa4fa4L;
56 for (int i = 0; i < xBuf.Length; i++)
60 for (int i = 0; i != W.Length; i++)
65 public override void Initialize ()
67 Initialize (true); // reuse instance
72 protected override void HashCore (byte[] rgb, int start, int count)
74 // fill the current word
75 while ((xBufOff != 0) && (count > 0)) {
81 // process whole words.
82 while (count > xBuf.Length) {
83 processWord (rgb, start);
86 byteCount1 += (ulong) xBuf.Length;
89 // load in the remainder.
97 protected override byte[] HashFinal ()
101 ulong lowBitLength = byteCount1 << 3;
102 ulong hiBitLength = byteCount2;
104 // add the pad bytes.
105 update ( (byte) 128);
109 processLength (lowBitLength, hiBitLength);
112 byte[] output = new byte [48];
113 unpackWord(H1, output, 0);
114 unpackWord(H2, output, 8);
115 unpackWord(H3, output, 16);
116 unpackWord(H4, output, 24);
117 unpackWord(H5, output, 32);
118 unpackWord(H6, output, 40);
124 private void update (byte input)
126 xBuf [xBufOff++] = input;
127 if (xBufOff == xBuf.Length) {
128 processWord(xBuf, 0);
134 private void processWord (byte[] input, int inOff)
136 W [wOff++] = ( (ulong) input [inOff] << 56)
137 | ( (ulong) input [inOff + 1] << 48)
138 | ( (ulong) input [inOff + 2] << 40)
139 | ( (ulong) input [inOff + 3] << 32)
140 | ( (ulong) input [inOff + 4] << 24)
141 | ( (ulong) input [inOff + 5] << 16)
142 | ( (ulong) input [inOff + 6] << 8)
143 | ( (ulong) input [inOff + 7]);
148 private void unpackWord (ulong word, byte[] output, int outOff)
150 output[outOff] = (byte) (word >> 56);
151 output[outOff + 1] = (byte) (word >> 48);
152 output[outOff + 2] = (byte) (word >> 40);
153 output[outOff + 3] = (byte) (word >> 32);
154 output[outOff + 4] = (byte) (word >> 24);
155 output[outOff + 5] = (byte) (word >> 16);
156 output[outOff + 6] = (byte) (word >> 8);
157 output[outOff + 7] = (byte) word;
160 // adjust the byte counts so that byteCount2 represents the
161 // upper long (less 3 bits) word of the byte count.
162 private void adjustByteCounts()
164 if (byteCount1 > 0x1fffffffffffffffL) {
165 byteCount2 += (byteCount1 >> 61);
166 byteCount1 &= 0x1fffffffffffffffL;
170 private void processLength (ulong lowW, ulong hiW)
178 private void processBlock ()
181 // expand 16 word block into 80 word blocks.
182 for (int t = 16; t <= 79; t++)
183 W[t] = Sigma1 (W [t - 2]) + W [t - 7] + Sigma0 (W [t - 15]) + W [t - 16];
185 // set up working variables.
195 for (int t = 0; t <= 79; t++) {
196 ulong T1 = h + Sum1 (e) + Ch (e, f, g) + SHAConstants.K2 [t] + W [t];
197 ulong T2 = Sum0 (a) + Maj (a, b, c);
216 // reset the offset and clean out the word buffer.
218 for (int i = 0; i != W.Length; i++)
222 private ulong rotateRight (ulong x, int n)
224 return (x >> n) | (x << (64 - n));
227 /* SHA-384 and SHA-512 functions (as for SHA-256 but for longs) */
228 private ulong Ch (ulong x, ulong y, ulong z)
230 return ((x & y) ^ ((~x) & z));
233 private ulong Maj (ulong x, ulong y, ulong z)
235 return ((x & y) ^ (x & z) ^ (y & z));
238 private ulong Sum0 (ulong x)
240 return rotateRight (x, 28) ^ rotateRight (x, 34) ^ rotateRight (x, 39);
243 private ulong Sum1 (ulong x)
245 return rotateRight (x, 14) ^ rotateRight (x, 18) ^ rotateRight (x, 41);
248 private ulong Sigma0 (ulong x)
250 return rotateRight (x, 1) ^ rotateRight(x, 8) ^ (x >> 7);
253 private ulong Sigma1 (ulong x)
255 return rotateRight (x, 19) ^ rotateRight (x, 61) ^ (x >> 6);