2002-11-01 Sebastien Pouliot <spouliot@videotron.ca>
[mono.git] / mcs / class / corlib / System.Security.Cryptography / SHA384Managed.cs
1 //
2 // System.Security.Cryptography.SHA384Managed.cs
3 //
4 // Authors:
5 //      Dan Lewis (dihlewis@yahoo.co.uk)
6 //      Sébastien Pouliot (spouliot@motus.com)
7 //
8 // (C) 2002
9 // Implementation translated from Bouncy Castle JCE (http://www.bouncycastle.org/)
10 // See bouncycastle.txt for license.
11 //
12
13 using System;
14
15 namespace System.Security.Cryptography {
16         
17 public class SHA384Managed : SHA384 {
18
19         private byte[] xBuf;
20         private int xBufOff;
21
22         [CLSCompliant(false)]
23         private ulong byteCount1;
24         [CLSCompliant(false)]
25         private ulong byteCount2;
26
27         [CLSCompliant(false)]
28         protected ulong H1, H2, H3, H4, H5, H6, H7, H8;
29
30         [CLSCompliant(false)]
31         private ulong[] W = new ulong [80];
32         private int wOff;
33
34         public SHA384Managed () 
35         {
36                 xBuf = new byte [8];
37                 xBufOff = 0;
38                 Initialize ();
39         }
40
41         public override void Initialize () 
42         {
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;
54
55                 byteCount1 = 0;
56                 byteCount2 = 0;
57
58                 xBufOff = 0;
59                 for (int i = 0; i < xBuf.Length; i++) 
60                         xBuf [i] = 0;
61
62                 wOff = 0;
63                 for (int i = 0; i != W.Length; i++)
64                         W [i] = 0;
65         }
66
67         // protected
68
69         protected override void HashCore (byte[] rgb, int start, int count) 
70         {
71                 // fill the current word
72                 while ((xBufOff != 0) && (count > 0)) {
73                         update( rgb [start]);
74                         start++;
75                         count--;
76                 }
77
78                 // process whole words.
79                 while (count > xBuf.Length) {
80                         processWord(rgb, start);
81                         start += xBuf.Length;
82                         count -= xBuf.Length;
83                         byteCount1 += (ulong) xBuf.Length;
84                 }
85
86                 // load in the remainder.
87                 while (count > 0) {
88                         update( rgb [start]);
89                         start++;
90                         count--;
91                 }
92         }
93
94         protected override byte[] HashFinal () 
95         {
96                 adjustByteCounts();
97
98                 ulong lowBitLength = byteCount1 << 3;
99                 ulong hiBitLength = byteCount2;
100
101                 // add the pad bytes.
102                 update ( (byte) 128);
103                 while (xBufOff != 0)
104                         update ( (byte)0);
105
106                 processLength (lowBitLength, hiBitLength);
107                 processBlock ();
108                 
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);
116
117                 Initialize ();
118                 return output;
119         }
120
121         private void update (byte input)
122         {
123                 xBuf [xBufOff++] = input;
124                 if (xBufOff == xBuf.Length) {
125                         processWord(xBuf, 0);
126                         xBufOff = 0;
127                 }
128                 byteCount1++;
129         }
130
131         private void processWord (byte[] input, int inOff)
132         {
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)); 
141                 if (wOff == 16)
142                         processBlock ();
143         }
144
145         private void unpackWord (ulong word, byte[] output, int outOff)
146         {
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;
155         }
156
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()
160         {
161                 if (byteCount1 > 0x1fffffffffffffffL) {
162                         byteCount2 += (byteCount1 >> 61);
163                         byteCount1 &= 0x1fffffffffffffffL;
164                 }
165         }
166
167         private void processLength (ulong lowW, ulong hiW)
168         {
169                 if (wOff > 14)
170                         processBlock();
171                 W[14] = hiW;
172                 W[15] = lowW;
173         }
174
175         private void processBlock ()
176         {
177                 adjustByteCounts ();
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];
181
182                 // set up working variables.
183                 ulong a = H1;
184                 ulong b = H2;
185                 ulong c = H3;
186                 ulong d = H4;
187                 ulong e = H5;
188                 ulong f = H6;
189                 ulong g = H7;
190                 ulong h = H8;
191
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);
195                         h = g;
196                         g = f;
197                         f = e;
198                         e = d + T1;
199                         d = c;
200                         c = b;
201                         b = a;
202                         a = T1 + T2;
203                 }
204
205                 H1 += a;
206                 H2 += b;
207                 H3 += c;
208                 H4 += d;
209                 H5 += e;
210                 H6 += f;
211                 H7 += g;
212                 H8 += h;
213                 // reset the offset and clean out the word buffer.
214                 wOff = 0;
215                 for (int i = 0; i != W.Length; i++)
216                         W[i] = 0;
217         }
218
219         private ulong rotateRight (ulong x, int n)
220         {
221                 return (x >> n) | (x << (64 - n));
222         }
223
224         /* SHA-384 and SHA-512 functions (as for SHA-256 but for longs) */
225         private ulong Ch (ulong x, ulong y, ulong z)
226         {
227                 return ((x & y) ^ ((~x) & z));
228         }
229
230         private ulong Maj (ulong x, ulong y, ulong z)
231         {
232                 return ((x & y) ^ (x & z) ^ (y & z));
233         }
234
235         private ulong Sum0 (ulong x)
236         {
237                 return rotateRight (x, 28) ^ rotateRight (x, 34) ^ rotateRight (x, 39);
238         }
239
240         private ulong Sum1 (ulong x)
241         {
242                 return rotateRight (x, 14) ^ rotateRight (x, 18) ^ rotateRight (x, 41);
243         }
244
245         private ulong Sigma0 (ulong x)
246         {
247                 return rotateRight (x, 1) ^ rotateRight(x, 8) ^ (x >> 7);
248         }
249
250         private ulong Sigma1 (ulong x)
251         {
252                 return rotateRight (x, 19) ^ rotateRight (x, 61) ^ (x >> 6);
253         }
254
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
258         static ulong[] K = {
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
279         };
280
281 }
282
283 }