New test.
[mono.git] / mcs / class / corlib / System.Security.Cryptography / RIPEMD160Managed.cs
1 //
2 // RIPEMD160Managed.cs: Implements the RIPEMD-160 hash algorithm
3 //
4 // Author:
5 //      Pieter Philippaerts (Pieter@mentalis.org)
6 //
7 //   References:
8 //     - http://www.esat.kuleuven.ac.be/~cosicart/ps/AB-9601/
9 //
10 // (C) 2003 The Mentalis.org Team (http://www.mentalis.org/)
11 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 #if NET_2_0
34
35 using System.Runtime.InteropServices;
36
37 namespace System.Security.Cryptography {
38         /// <summary>
39         /// Computes the <see cref="RIPEMD160"/> hash for the input data.
40         /// </summary>
41         [ComVisible (true)]
42         public class RIPEMD160Managed : RIPEMD160 { // not 'sealed' according to preliminary docs; this may change though
43                 /// <summary>
44                 /// Initializes a new instance of the <see cref="RIPEMD160Managed"/> class. This class cannot be inherited.
45                 /// </summary>
46                 public RIPEMD160Managed() {
47                         _X = new uint[16];
48                         _HashValue = new uint[5];
49                         _ProcessingBuffer = new byte[BLOCK_SIZE_BYTES];
50                         Initialize();
51                 }
52                 /// <summary>
53                 /// Initializes an instance of <see cref="RIPEMD160Managed"/>.
54                 /// </summary>
55                 /// <exception cref="ObjectDisposedException">The RIPEMD160Managed instance has been disposed.</exception>
56                 public override void Initialize() {
57                         _HashValue[0] = 0x67452301;
58                         _HashValue[1] = 0xefcdab89;
59                         _HashValue[2] = 0x98badcfe;
60                         _HashValue[3] = 0x10325476;
61                         _HashValue[4] = 0xc3d2e1f0;
62                         _Length = 0;
63                         _ProcessingBufferCount = 0;
64                         Array.Clear (_X, 0, _X.Length);
65                         Array.Clear (_ProcessingBuffer, 0, _ProcessingBuffer.Length);
66                 }
67                 /// <summary>
68                 /// Routes data written to the object into the <see cref="RIPEMD160"/> hash algorithm for computing the hash.
69                 /// </summary>
70                 /// <param name="array">The array of data bytes.</param>
71                 /// <param name="ibStart">The offset into the byte array from which to begin using data.</param>
72                 /// <param name="cbSize">The number of bytes in the array to use as data.</param>
73                 /// <exception cref="ObjectDisposedException">The <see cref="RIPEMD160Managed"/> instance has been disposed.</exception>
74                 protected override void HashCore(byte[] array, int ibStart, int cbSize) {
75                         int i;
76                         State = 1;
77
78                         _Length += (uint)cbSize; // global length
79
80                         if (_ProcessingBufferCount != 0) {
81                                 if (cbSize < (BLOCK_SIZE_BYTES - _ProcessingBufferCount)) {
82                                         System.Buffer.BlockCopy (array, ibStart, _ProcessingBuffer, _ProcessingBufferCount, cbSize);
83                                         _ProcessingBufferCount += cbSize;
84                                         return;
85                                 } else {
86                                         i = (BLOCK_SIZE_BYTES - _ProcessingBufferCount);
87                                         System.Buffer.BlockCopy (array, ibStart, _ProcessingBuffer, _ProcessingBufferCount, i);
88                                         ProcessBlock (_ProcessingBuffer, 0);
89                                         _ProcessingBufferCount = 0;
90                                         ibStart += i;
91                                         cbSize -= i;
92                                 }
93                         }
94
95                         for (i=0; i<cbSize-cbSize%BLOCK_SIZE_BYTES; i += BLOCK_SIZE_BYTES) {
96                                 ProcessBlock (array, ibStart+i);
97                         }
98
99                         if (cbSize%BLOCK_SIZE_BYTES != 0) {
100                                 System.Buffer.BlockCopy (array, cbSize-cbSize%BLOCK_SIZE_BYTES+ibStart, _ProcessingBuffer, 0, cbSize%BLOCK_SIZE_BYTES);
101                                 _ProcessingBufferCount = cbSize%BLOCK_SIZE_BYTES;
102                         }
103                 }
104                 /// <summary>
105                 /// Returns the computed <see cref="RIPEMD160"/> hash as an array of bytes after all data has been written to the object.
106                 /// </summary>
107                 /// <returns>The computed hash value.</returns>
108                 /// <exception cref="ObjectDisposedException">The <see cref="RIPEMD160Managed"/> instance has been disposed.</exception>
109                 protected override byte[] HashFinal() {
110                         CompressFinal(_Length);
111                         byte[] hash = new byte[20];
112                         if (BitConverter.IsLittleEndian) {
113                                 for (int i = 0; i < 5; i++) {
114                                         for (int j = 0; j < 4; j++) {
115                                                 hash [i*4+j] = (byte)(_HashValue [i] >> j*8);
116                                         }
117                                 }
118                         } else {
119                                 Buffer.BlockCopy (_HashValue, 0, hash, 0, 20);
120                         }
121                         return hash;
122                 }
123                 /// <summary>
124                 /// Finalizes the RIPEMD160Managed.
125                 /// </summary>
126                 ~RIPEMD160Managed() {
127                         Dispose(false);
128                 }
129
130                 /// <summary>
131                 /// Processes one block of data.
132                 /// </summary>
133                 /// <param name="buffer">The buffer with the data.</param>
134                 /// <param name="offset">The offset in the buffer.</param>
135                 private void ProcessBlock (byte[] buffer, int offset)
136                 {
137                         if (BitConverter.IsLittleEndian) {
138                                 for (int i=0; i < _X.Length; i++) {
139                                         _X [i] = (uint)(buffer [offset])
140                                                 | (((uint)(buffer [offset+1])) <<  8)
141                                                 | (((uint)(buffer [offset+2])) << 16)
142                                                 | (((uint)(buffer [offset+3])) << 24);
143                                         offset += 4;
144                                 }
145                         } else {
146                                 Buffer.BlockCopy (buffer, offset, _X, 0, 64);
147                         }
148                         Compress();
149                 }
150
151                 private void Compress() {
152                         uint aa = _HashValue[0],  bb = _HashValue[1],  cc = _HashValue[2],  dd = _HashValue[3],  ee = _HashValue[4];
153                         uint aaa = _HashValue[0], bbb = _HashValue[1], ccc = _HashValue[2], ddd = _HashValue[3], eee = _HashValue[4];
154                         /* round 1 */
155                         FF(ref aa, bb, ref cc, dd, ee, _X[ 0], 11);
156                         FF(ref ee, aa, ref bb, cc, dd, _X[ 1], 14);
157                         FF(ref dd, ee, ref aa, bb, cc, _X[ 2], 15);
158                         FF(ref cc, dd, ref ee, aa, bb, _X[ 3], 12);
159                         FF(ref bb, cc, ref dd, ee, aa, _X[ 4],  5);
160                         FF(ref aa, bb, ref cc, dd, ee, _X[ 5],  8);
161                         FF(ref ee, aa, ref bb, cc, dd, _X[ 6],  7);
162                         FF(ref dd, ee, ref aa, bb, cc, _X[ 7],  9);
163                         FF(ref cc, dd, ref ee, aa, bb, _X[ 8], 11);
164                         FF(ref bb, cc, ref dd, ee, aa, _X[ 9], 13);
165                         FF(ref aa, bb, ref cc, dd, ee, _X[10], 14);
166                         FF(ref ee, aa, ref bb, cc, dd, _X[11], 15);
167                         FF(ref dd, ee, ref aa, bb, cc, _X[12],  6);
168                         FF(ref cc, dd, ref ee, aa, bb, _X[13],  7);
169                         FF(ref bb, cc, ref dd, ee, aa, _X[14],  9);
170                         FF(ref aa, bb, ref cc, dd, ee, _X[15],  8);
171                         /* round 2 */
172                         GG(ref ee, aa, ref bb, cc, dd, _X[ 7],  7);
173                         GG(ref dd, ee, ref aa, bb, cc, _X[ 4],  6);
174                         GG(ref cc, dd, ref ee, aa, bb, _X[13],  8);
175                         GG(ref bb, cc, ref dd, ee, aa, _X[ 1], 13);
176                         GG(ref aa, bb, ref cc, dd, ee, _X[10], 11);
177                         GG(ref ee, aa, ref bb, cc, dd, _X[ 6],  9);
178                         GG(ref dd, ee, ref aa, bb, cc, _X[15],  7);
179                         GG(ref cc, dd, ref ee, aa, bb, _X[ 3], 15);
180                         GG(ref bb, cc, ref dd, ee, aa, _X[12],  7);
181                         GG(ref aa, bb, ref cc, dd, ee, _X[ 0], 12);
182                         GG(ref ee, aa, ref bb, cc, dd, _X[ 9], 15);
183                         GG(ref dd, ee, ref aa, bb, cc, _X[ 5],  9);
184                         GG(ref cc, dd, ref ee, aa, bb, _X[ 2], 11);
185                         GG(ref bb, cc, ref dd, ee, aa, _X[14],  7);
186                         GG(ref aa, bb, ref cc, dd, ee, _X[11], 13);
187                         GG(ref ee, aa, ref bb, cc, dd, _X[ 8], 12);
188                         /* round 3 */
189                         HH(ref dd, ee, ref aa, bb, cc, _X[ 3], 11);
190                         HH(ref cc, dd, ref ee, aa, bb, _X[10], 13);
191                         HH(ref bb, cc, ref dd, ee, aa, _X[14],  6);
192                         HH(ref aa, bb, ref cc, dd, ee, _X[ 4],  7);
193                         HH(ref ee, aa, ref bb, cc, dd, _X[ 9], 14);
194                         HH(ref dd, ee, ref aa, bb, cc, _X[15],  9);
195                         HH(ref cc, dd, ref ee, aa, bb, _X[ 8], 13);
196                         HH(ref bb, cc, ref dd, ee, aa, _X[ 1], 15);
197                         HH(ref aa, bb, ref cc, dd, ee, _X[ 2], 14);
198                         HH(ref ee, aa, ref bb, cc, dd, _X[ 7],  8);
199                         HH(ref dd, ee, ref aa, bb, cc, _X[ 0], 13);
200                         HH(ref cc, dd, ref ee, aa, bb, _X[ 6],  6);
201                         HH(ref bb, cc, ref dd, ee, aa, _X[13],  5);
202                         HH(ref aa, bb, ref cc, dd, ee, _X[11], 12);
203                         HH(ref ee, aa, ref bb, cc, dd, _X[ 5],  7);
204                         HH(ref dd, ee, ref aa, bb, cc, _X[12],  5);
205                         /* round 4 */
206                         II(ref cc, dd, ref ee, aa, bb, _X[ 1], 11);
207                         II(ref bb, cc, ref dd, ee, aa, _X[ 9], 12);
208                         II(ref aa, bb, ref cc, dd, ee, _X[11], 14);
209                         II(ref ee, aa, ref bb, cc, dd, _X[10], 15);
210                         II(ref dd, ee, ref aa, bb, cc, _X[ 0], 14);
211                         II(ref cc, dd, ref ee, aa, bb, _X[ 8], 15);
212                         II(ref bb, cc, ref dd, ee, aa, _X[12],  9);
213                         II(ref aa, bb, ref cc, dd, ee, _X[ 4],  8);
214                         II(ref ee, aa, ref bb, cc, dd, _X[13],  9);
215                         II(ref dd, ee, ref aa, bb, cc, _X[ 3], 14);
216                         II(ref cc, dd, ref ee, aa, bb, _X[ 7],  5);
217                         II(ref bb, cc, ref dd, ee, aa, _X[15],  6);
218                         II(ref aa, bb, ref cc, dd, ee, _X[14],  8);
219                         II(ref ee, aa, ref bb, cc, dd, _X[ 5],  6);
220                         II(ref dd, ee, ref aa, bb, cc, _X[ 6],  5);
221                         II(ref cc, dd, ref ee, aa, bb, _X[ 2], 12);
222                         /* round 5 */
223                         JJ(ref bb, cc, ref dd, ee, aa, _X[ 4],  9);
224                         JJ(ref aa, bb, ref cc, dd, ee, _X[ 0], 15);
225                         JJ(ref ee, aa, ref bb, cc, dd, _X[ 5],  5);
226                         JJ(ref dd, ee, ref aa, bb, cc, _X[ 9], 11);
227                         JJ(ref cc, dd, ref ee, aa, bb, _X[ 7],  6);
228                         JJ(ref bb, cc, ref dd, ee, aa, _X[12],  8);
229                         JJ(ref aa, bb, ref cc, dd, ee, _X[ 2], 13);
230                         JJ(ref ee, aa, ref bb, cc, dd, _X[10], 12);
231                         JJ(ref dd, ee, ref aa, bb, cc, _X[14],  5);
232                         JJ(ref cc, dd, ref ee, aa, bb, _X[ 1], 12);
233                         JJ(ref bb, cc, ref dd, ee, aa, _X[ 3], 13);
234                         JJ(ref aa, bb, ref cc, dd, ee, _X[ 8], 14);
235                         JJ(ref ee, aa, ref bb, cc, dd, _X[11], 11);
236                         JJ(ref dd, ee, ref aa, bb, cc, _X[ 6],  8);
237                         JJ(ref cc, dd, ref ee, aa, bb, _X[15],  5);
238                         JJ(ref bb, cc, ref dd, ee, aa, _X[13],  6);
239                         /* parallel round 1 */
240                         JJJ(ref aaa, bbb, ref ccc, ddd, eee, _X[ 5],  8);
241                         JJJ(ref eee, aaa, ref bbb, ccc, ddd, _X[14],  9);
242                         JJJ(ref ddd, eee, ref aaa, bbb, ccc, _X[ 7],  9);
243                         JJJ(ref ccc, ddd, ref eee, aaa, bbb, _X[ 0], 11);
244                         JJJ(ref bbb, ccc, ref ddd, eee, aaa, _X[ 9], 13);
245                         JJJ(ref aaa, bbb, ref ccc, ddd, eee, _X[ 2], 15);
246                         JJJ(ref eee, aaa, ref bbb, ccc, ddd, _X[11], 15);
247                         JJJ(ref ddd, eee, ref aaa, bbb, ccc, _X[ 4],  5);
248                         JJJ(ref ccc, ddd, ref eee, aaa, bbb, _X[13],  7);
249                         JJJ(ref bbb, ccc, ref ddd, eee, aaa, _X[ 6],  7);
250                         JJJ(ref aaa, bbb, ref ccc, ddd, eee, _X[15],  8);
251                         JJJ(ref eee, aaa, ref bbb, ccc, ddd, _X[ 8], 11);
252                         JJJ(ref ddd, eee, ref aaa, bbb, ccc, _X[ 1], 14);
253                         JJJ(ref ccc, ddd, ref eee, aaa, bbb, _X[10], 14);
254                         JJJ(ref bbb, ccc, ref ddd, eee, aaa, _X[ 3], 12);
255                         JJJ(ref aaa, bbb, ref ccc, ddd, eee, _X[12],  6);
256                         /* parallel round 2 */
257                         III(ref eee, aaa, ref bbb, ccc, ddd, _X[ 6],  9); 
258                         III(ref ddd, eee, ref aaa, bbb, ccc, _X[11], 13);
259                         III(ref ccc, ddd, ref eee, aaa, bbb, _X[ 3], 15);
260                         III(ref bbb, ccc, ref ddd, eee, aaa, _X[ 7],  7);
261                         III(ref aaa, bbb, ref ccc, ddd, eee, _X[ 0], 12);
262                         III(ref eee, aaa, ref bbb, ccc, ddd, _X[13],  8);
263                         III(ref ddd, eee, ref aaa, bbb, ccc, _X[ 5],  9);
264                         III(ref ccc, ddd, ref eee, aaa, bbb, _X[10], 11);
265                         III(ref bbb, ccc, ref ddd, eee, aaa, _X[14],  7);
266                         III(ref aaa, bbb, ref ccc, ddd, eee, _X[15],  7);
267                         III(ref eee, aaa, ref bbb, ccc, ddd, _X[ 8], 12);
268                         III(ref ddd, eee, ref aaa, bbb, ccc, _X[12],  7);
269                         III(ref ccc, ddd, ref eee, aaa, bbb, _X[ 4],  6);
270                         III(ref bbb, ccc, ref ddd, eee, aaa, _X[ 9], 15);
271                         III(ref aaa, bbb, ref ccc, ddd, eee, _X[ 1], 13);
272                         III(ref eee, aaa, ref bbb, ccc, ddd, _X[ 2], 11);
273                         /* parallel round 3 */
274                         HHH(ref ddd, eee, ref aaa, bbb, ccc, _X[15],  9);
275                         HHH(ref ccc, ddd, ref eee, aaa, bbb, _X[ 5],  7);
276                         HHH(ref bbb, ccc, ref ddd, eee, aaa, _X[ 1], 15);
277                         HHH(ref aaa, bbb, ref ccc, ddd, eee, _X[ 3], 11);
278                         HHH(ref eee, aaa, ref bbb, ccc, ddd, _X[ 7],  8);
279                         HHH(ref ddd, eee, ref aaa, bbb, ccc, _X[14],  6);
280                         HHH(ref ccc, ddd, ref eee, aaa, bbb, _X[ 6],  6);
281                         HHH(ref bbb, ccc, ref ddd, eee, aaa, _X[ 9], 14);
282                         HHH(ref aaa, bbb, ref ccc, ddd, eee, _X[11], 12);
283                         HHH(ref eee, aaa, ref bbb, ccc, ddd, _X[ 8], 13);
284                         HHH(ref ddd, eee, ref aaa, bbb, ccc, _X[12],  5);
285                         HHH(ref ccc, ddd, ref eee, aaa, bbb, _X[ 2], 14);
286                         HHH(ref bbb, ccc, ref ddd, eee, aaa, _X[10], 13);
287                         HHH(ref aaa, bbb, ref ccc, ddd, eee, _X[ 0], 13);
288                         HHH(ref eee, aaa, ref bbb, ccc, ddd, _X[ 4],  7);
289                         HHH(ref ddd, eee, ref aaa, bbb, ccc, _X[13],  5);
290                         /* parallel round 4 */   
291                         GGG(ref ccc, ddd, ref eee, aaa, bbb, _X[ 8], 15);
292                         GGG(ref bbb, ccc, ref ddd, eee, aaa, _X[ 6],  5);
293                         GGG(ref aaa, bbb, ref ccc, ddd, eee, _X[ 4],  8);
294                         GGG(ref eee, aaa, ref bbb, ccc, ddd, _X[ 1], 11);
295                         GGG(ref ddd, eee, ref aaa, bbb, ccc, _X[ 3], 14);
296                         GGG(ref ccc, ddd, ref eee, aaa, bbb, _X[11], 14);
297                         GGG(ref bbb, ccc, ref ddd, eee, aaa, _X[15],  6);
298                         GGG(ref aaa, bbb, ref ccc, ddd, eee, _X[ 0], 14);
299                         GGG(ref eee, aaa, ref bbb, ccc, ddd, _X[ 5],  6);
300                         GGG(ref ddd, eee, ref aaa, bbb, ccc, _X[12],  9);
301                         GGG(ref ccc, ddd, ref eee, aaa, bbb, _X[ 2], 12);
302                         GGG(ref bbb, ccc, ref ddd, eee, aaa, _X[13],  9);
303                         GGG(ref aaa, bbb, ref ccc, ddd, eee, _X[ 9], 12);
304                         GGG(ref eee, aaa, ref bbb, ccc, ddd, _X[ 7],  5);
305                         GGG(ref ddd, eee, ref aaa, bbb, ccc, _X[10], 15);
306                         GGG(ref ccc, ddd, ref eee, aaa, bbb, _X[14],  8);
307                         /* parallel round 5 */
308                         FFF(ref bbb, ccc, ref ddd, eee, aaa, _X[12],  8);
309                         FFF(ref aaa, bbb, ref ccc, ddd, eee, _X[15],  5);
310                         FFF(ref eee, aaa, ref bbb, ccc, ddd, _X[10], 12);
311                         FFF(ref ddd, eee, ref aaa, bbb, ccc, _X[ 4],  9);
312                         FFF(ref ccc, ddd, ref eee, aaa, bbb, _X[ 1], 12);
313                         FFF(ref bbb, ccc, ref ddd, eee, aaa, _X[ 5],  5);
314                         FFF(ref aaa, bbb, ref ccc, ddd, eee, _X[ 8], 14);
315                         FFF(ref eee, aaa, ref bbb, ccc, ddd, _X[ 7],  6);
316                         FFF(ref ddd, eee, ref aaa, bbb, ccc, _X[ 6],  8);
317                         FFF(ref ccc, ddd, ref eee, aaa, bbb, _X[ 2], 13);
318                         FFF(ref bbb, ccc, ref ddd, eee, aaa, _X[13],  6);
319                         FFF(ref aaa, bbb, ref ccc, ddd, eee, _X[14],  5);
320                         FFF(ref eee, aaa, ref bbb, ccc, ddd, _X[ 0], 15);
321                         FFF(ref ddd, eee, ref aaa, bbb, ccc, _X[ 3], 13);
322                         FFF(ref ccc, ddd, ref eee, aaa, bbb, _X[ 9], 11);
323                         FFF(ref bbb, ccc, ref ddd, eee, aaa, _X[11], 11);
324                         /* combine results */
325                         ddd += cc + _HashValue[1];               /* final result for _HashValue[0] */
326                         _HashValue[1] = _HashValue[2] + dd + eee;
327                         _HashValue[2] = _HashValue[3] + ee + aaa;
328                         _HashValue[3] = _HashValue[4] + aa + bbb;
329                         _HashValue[4] = _HashValue[0] + bb + ccc;
330                         _HashValue[0] = ddd;
331                 }
332                 private void CompressFinal(ulong length) {
333                         uint lswlen = (uint)(length & 0xFFFFFFFF);
334                         uint mswlen = (uint)(length >> 32);
335                         // clear _X
336                         Array.Clear(_X, 0, _X.Length);
337                         // put bytes from _ProcessingBuffer into _X
338                         int ptr = 0;
339                         for (uint i = 0; i < (lswlen & 63); i++) {
340                                 // byte i goes into word X[i div 4] at pos.  8*(i mod 4)
341                                 _X[i >> 2] ^= ((uint)_ProcessingBuffer[ptr++]) << (int)(8 * (i & 3));
342                         }
343                         // append the bit m_n == 1
344                         _X[(lswlen >> 2) & 15] ^= (uint)1 << (int)(8 * (lswlen & 3) + 7);
345                         if ((lswlen & 63) > 55) {
346                                 // length goes to next block
347                                 Compress();
348                                 Array.Clear(_X, 0, _X.Length);
349                         }
350                         // append length in bits
351                         _X[14] = lswlen << 3;
352                         _X[15] = (lswlen >> 29) | (mswlen << 3);
353                         Compress();
354                 }
355
356                 // the following methods should be inlined by the compiler
357                 private uint ROL(uint x, int n) {
358                         return (((x) << (n)) | ((x) >> (32-(n))));
359                 }
360                 private uint F(uint x, uint y, uint z) {
361                         return ((x) ^ (y) ^ (z)) ;
362                 }
363                 private uint G(uint x, uint y, uint z) {
364                         return (((x) & (y)) | (~(x) & (z)));
365                 }
366                 private uint H(uint x, uint y, uint z) {
367                         return (((x) | ~(y)) ^ (z));
368                 }
369                 private uint I(uint x, uint y, uint z) {
370                         return (((x) & (z)) | ((y) & ~(z)));
371                 }
372                 private uint J(uint x, uint y, uint z) {
373                         return ((x) ^ ((y) | ~(z)));
374                 }
375                 private void FF(ref uint a, uint b, ref uint c, uint d, uint e, uint x, int s) {
376                         a += F(b, c, d) + x;
377                         a = ROL(a, s) + e;
378                         c = ROL(c, 10);
379                 }
380                 private void GG(ref uint a, uint b, ref uint c, uint d, uint e, uint x, int s) {
381                         a += G(b, c, d) + x + 0x5a827999;
382                         a = ROL(a, s) + e;
383                         c = ROL(c, 10);
384                 }
385                 private void HH(ref uint a, uint b, ref uint c, uint d, uint e, uint x, int s) {
386                         a += H(b, c, d) + x + 0x6ed9eba1;
387                         a = ROL(a, s) + e;
388                         c = ROL(c, 10);
389                 }
390                 private void II(ref uint a, uint b, ref uint c, uint d, uint e, uint x, int s) {
391                         a += I(b, c, d) + x + 0x8f1bbcdc;
392                         a = ROL(a, s) + e;
393                         c = ROL(c, 10);
394                 }
395                 private void JJ(ref uint a, uint b, ref uint c, uint d, uint e, uint x, int s) {
396                         a += J(b, c, d) + x + 0xa953fd4e;
397                         a = ROL(a, s) + e;
398                         c = ROL(c, 10);
399                 }
400                 private void FFF(ref uint a, uint b, ref uint c, uint d, uint e, uint x, int s) {
401                         a += F(b, c, d) + x;
402                         a = ROL(a, s) + e;
403                         c = ROL(c, 10);
404                 }
405                 private void GGG(ref uint a, uint b, ref uint c, uint d, uint e, uint x, int s) {
406                         a += G(b, c, d) + x + 0x7a6d76e9;
407                         a = ROL(a, s) + e;
408                         c = ROL(c, 10);
409                 }
410                 private void HHH(ref uint a, uint b, ref uint c, uint d, uint e, uint x, int s) {
411                         a += H(b, c, d) + x + 0x6d703ef3;
412                         a = ROL(a, s) + e;
413                         c = ROL(c, 10);
414                 }
415                 private void III(ref uint a, uint b, ref uint c, uint d, uint e, uint x, int s) {
416                         a += I(b, c, d) + x + 0x5c4dd124;
417                         a = ROL(a, s) + e;
418                         c = ROL(c, 10);
419                 }
420                 private void JJJ(ref uint a, uint b, ref uint c, uint d, uint e, uint x, int s) {
421                         a += J(b, c, d) + x + 0x50a28be6;
422                         a = ROL(a, s) + e;
423                         c = ROL(c, 10);
424                 }
425
426                 /// <summary>
427                 /// A buffer that holds the extra data.
428                 /// </summary>
429                 private byte[] _ProcessingBuffer;
430                 /// <summary>
431                 /// The X vectors.
432                 /// </summary>
433                 private uint[] _X;
434                 /// <summary>
435                 /// The current value of the hash.
436                 /// </summary>
437                 private uint[] _HashValue;
438                 /// <summary>
439                 /// The number of bytes hashed.
440                 /// </summary>
441                 private ulong _Length;
442
443                 private int _ProcessingBufferCount; // Counts how much data we have stored that still needs processed.
444
445                 private const int BLOCK_SIZE_BYTES =  64;
446         }
447 }
448
449 #endif