merged Sys.Web.Services 2.0 support in my branch:
[mono.git] / mcs / class / corlib / System.Security.Cryptography / SHA1CryptoServiceProvider.cs
1 //
2 // System.Security.Cryptography SHA1CryptoServiceProvider Class implementation
3 //
4 // Authors:
5 //      Matthew S. Ford (Matthew.S.Ford@Rose-Hulman.Edu)
6 //      Sebastien Pouliot (sebastien@ximian.com)
7 //
8 // Copyright 2001 by Matthew S. Ford.
9 // Copyright (C) 2004, 2005 Novell, Inc (http://www.novell.com)
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 // Note:
32 // The MS Framework includes two (almost) identical class for SHA1.
33 //      SHA1Managed is a 100% managed implementation.
34 //      SHA1CryptoServiceProvider (this file) is a wrapper on CryptoAPI.
35 // Mono must provide those two class for binary compatibility.
36 // In our case both class are wrappers around a managed internal class SHA1Internal.
37
38 using System.Runtime.InteropServices;
39
40 namespace System.Security.Cryptography {
41
42         internal class SHA1Internal {
43         
44                 private const int BLOCK_SIZE_BYTES =  64;
45                 private const int HASH_SIZE_BYTES  =  20;
46                 private uint[] _H;  // these are my chaining variables
47                 private ulong count;
48                 private byte[] _ProcessingBuffer;   // Used to start data when passed less than a block worth.
49                 private int _ProcessingBufferCount; // Counts how much data we have stored that still needs processed.
50                 private uint[] buff;
51
52                 public SHA1Internal () 
53                 {
54                         _H = new uint[5];
55                         _ProcessingBuffer = new byte[BLOCK_SIZE_BYTES];
56                         buff = new uint[80];
57                         
58                         Initialize();
59                 }
60
61                 public void HashCore (byte[] rgb, int start, int size) 
62                 {
63                         int i;
64
65                         if (_ProcessingBufferCount != 0) {
66                                 if (size < (BLOCK_SIZE_BYTES - _ProcessingBufferCount)) {
67                                         System.Buffer.BlockCopy (rgb, start, _ProcessingBuffer, _ProcessingBufferCount, size);
68                                         _ProcessingBufferCount += size;
69                                         return;
70                                 }
71                                 else {
72                                         i = (BLOCK_SIZE_BYTES - _ProcessingBufferCount);
73                                         System.Buffer.BlockCopy (rgb, start, _ProcessingBuffer, _ProcessingBufferCount, i);
74                                         ProcessBlock (_ProcessingBuffer, 0);
75                                         _ProcessingBufferCount = 0;
76                                         start += i;
77                                         size -= i;
78                                 }
79                         }
80
81                         for (i=0; i<size-size%BLOCK_SIZE_BYTES; i += BLOCK_SIZE_BYTES) {
82                                 ProcessBlock (rgb, start+i);
83                         }
84
85                         if (size%BLOCK_SIZE_BYTES != 0) {
86                                 System.Buffer.BlockCopy (rgb, size-size%BLOCK_SIZE_BYTES+start, _ProcessingBuffer, 0, size%BLOCK_SIZE_BYTES);
87                                 _ProcessingBufferCount = size%BLOCK_SIZE_BYTES;
88                         }
89                 }
90         
91                 public byte[] HashFinal () 
92                 {
93                         byte[] hash = new byte[20];
94
95                         ProcessFinalBlock (_ProcessingBuffer, 0, _ProcessingBufferCount);
96
97                         for (int i=0; i<5; i++) {
98                                 for (int j=0; j<4; j++) {
99                                         hash [i*4+j] = (byte)(_H[i] >> (8*(3-j)));
100                                 }
101                         }
102
103                         return hash;
104                 }
105
106                 public void Initialize () 
107                 {
108                         count = 0;
109                         _ProcessingBufferCount = 0;
110
111                         _H[0] = 0x67452301;
112                         _H[1] = 0xefcdab89;
113                         _H[2] = 0x98badcfe;
114                         _H[3] = 0x10325476;
115                         _H[4] = 0xC3D2E1F0;
116                 }
117
118                 private void ProcessBlock(byte[] inputBuffer, int inputOffset) 
119                 {
120                         uint a, b, c, d, e;
121                         int i;
122
123                         count += BLOCK_SIZE_BYTES;
124                 
125                         for (i=0; i<16; i++) {
126                                 buff[i] = ((uint)(inputBuffer[inputOffset+4*i]) << 24)
127                                         | ((uint)(inputBuffer[inputOffset+4*i+1]) << 16)
128                                         | ((uint)(inputBuffer[inputOffset+4*i+2]) <<  8)
129                                         | ((uint)(inputBuffer[inputOffset+4*i+3]));
130                         }
131
132                         for (i=16; i<80; i++) {
133                                 buff[i] = ((buff[i-3] ^ buff[i-8] ^ buff[i-14] ^ buff[i-16]) << 1)
134                                         | ((buff[i-3] ^ buff[i-8] ^ buff[i-14] ^ buff[i-16]) >> 31);
135                         }
136                 
137                         a = _H[0];
138                         b = _H[1];
139                         c = _H[2];
140                         d = _H[3];
141                         e = _H[4];
142
143                         // This function was unrolled because it seems to be doubling our performance with current compiler/VM.
144                         // Possibly roll up if this changes.
145         
146                         // ---- Round 1 --------
147   
148                         e += ((a << 5) | (a >> 27)) + (((c ^ d) & b) ^ d) + 0x5A827999 + buff[0];
149                         b = (b << 30) | (b >> 2);
150
151                         d += ((e << 5) | (e >> 27)) + (((b ^ c) & a) ^ c) + 0x5A827999 + buff[1];
152                         a = (a << 30) | (a >> 2);
153
154                         c += ((d << 5) | (d >> 27)) + (((a ^ b) & e) ^ b) + 0x5A827999 + buff[2];
155                         e = (e << 30) | (e >> 2);
156
157                         b += ((c << 5) | (c >> 27)) + (((e ^ a) & d) ^ a) + 0x5A827999 + buff[3];
158                         d = (d << 30) | (d >> 2);
159
160                         a += ((b << 5) | (b >> 27)) + (((d ^ e) & c) ^ e) + 0x5A827999 + buff[4];
161                         c = (c << 30) | (c >> 2);
162
163                         e += ((a << 5) | (a >> 27)) + (((c ^ d) & b) ^ d) + 0x5A827999 + buff[5];
164                         b = (b << 30) | (b >> 2);
165
166                         d += ((e << 5) | (e >> 27)) + (((b ^ c) & a) ^ c) + 0x5A827999 + buff[6];
167                         a = (a << 30) | (a >> 2);
168
169                         c += ((d << 5) | (d >> 27)) + (((a ^ b) & e) ^ b) + 0x5A827999 + buff[7];
170                         e = (e << 30) | (e >> 2);
171
172                         b += ((c << 5) | (c >> 27)) + (((e ^ a) & d) ^ a) + 0x5A827999 + buff[8];
173                         d = (d << 30) | (d >> 2);
174
175                         a += ((b << 5) | (b >> 27)) + (((d ^ e) & c) ^ e) + 0x5A827999 + buff[9];
176                         c = (c << 30) | (c >> 2);
177
178                         e += ((a << 5) | (a >> 27)) + (((c ^ d) & b) ^ d) + 0x5A827999 + buff[10];
179                         b = (b << 30) | (b >> 2);
180
181                         d += ((e << 5) | (e >> 27)) + (((b ^ c) & a) ^ c) + 0x5A827999 + buff[11];
182                         a = (a << 30) | (a >> 2);
183
184                         c += ((d << 5) | (d >> 27)) + (((a ^ b) & e) ^ b) + 0x5A827999 + buff[12];
185                         e = (e << 30) | (e >> 2);
186
187                         b += ((c << 5) | (c >> 27)) + (((e ^ a) & d) ^ a) + 0x5A827999 + buff[13];
188                         d = (d << 30) | (d >> 2);
189
190                         a += ((b << 5) | (b >> 27)) + (((d ^ e) & c) ^ e) + 0x5A827999 + buff[14];
191                         c = (c << 30) | (c >> 2);
192
193                         e += ((a << 5) | (a >> 27)) + (((c ^ d) & b) ^ d) + 0x5A827999 + buff[15];
194                         b = (b << 30) | (b >> 2);
195
196                         d += ((e << 5) | (e >> 27)) + (((b ^ c) & a) ^ c) + 0x5A827999 + buff[16];
197                         a = (a << 30) | (a >> 2);
198
199                         c += ((d << 5) | (d >> 27)) + (((a ^ b) & e) ^ b) + 0x5A827999 + buff[17];
200                         e = (e << 30) | (e >> 2);
201
202                         b += ((c << 5) | (c >> 27)) + (((e ^ a) & d) ^ a) + 0x5A827999 + buff[18];
203                         d = (d << 30) | (d >> 2);
204
205                         a += ((b << 5) | (b >> 27)) + (((d ^ e) & c) ^ e) + 0x5A827999 + buff[19];
206                         c = (c << 30) | (c >> 2);
207
208                         // ---- Round 2 --------
209   
210                         e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0x6ED9EBA1 + buff[20];
211                         b = (b << 30) | (b >> 2);
212
213                         d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0x6ED9EBA1 + buff[21];
214                         a = (a << 30) | (a >> 2);
215
216                         c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0x6ED9EBA1 + buff[22];
217                         e = (e << 30) | (e >> 2);
218
219                         b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0x6ED9EBA1 + buff[23];
220                         d = (d << 30) | (d >> 2);
221
222                         a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0x6ED9EBA1 + buff[24];
223                         c = (c << 30) | (c >> 2);
224
225                         e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0x6ED9EBA1 + buff[25];
226                         b = (b << 30) | (b >> 2);
227
228                         d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0x6ED9EBA1 + buff[26];
229                         a = (a << 30) | (a >> 2);
230
231                         c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0x6ED9EBA1 + buff[27];
232                         e = (e << 30) | (e >> 2);
233
234                         b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0x6ED9EBA1 + buff[28];
235                         d = (d << 30) | (d >> 2);
236
237                         a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0x6ED9EBA1 + buff[29];
238                         c = (c << 30) | (c >> 2);
239
240                         e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0x6ED9EBA1 + buff[30];
241                         b = (b << 30) | (b >> 2);
242
243                         d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0x6ED9EBA1 + buff[31];
244                         a = (a << 30) | (a >> 2);
245
246                         c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0x6ED9EBA1 + buff[32];
247                         e = (e << 30) | (e >> 2);
248
249                         b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0x6ED9EBA1 + buff[33];
250                         d = (d << 30) | (d >> 2);
251
252                         a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0x6ED9EBA1 + buff[34];
253                         c = (c << 30) | (c >> 2);
254
255                         e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0x6ED9EBA1 + buff[35];
256                         b = (b << 30) | (b >> 2);
257
258                         d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0x6ED9EBA1 + buff[36];
259                         a = (a << 30) | (a >> 2);
260
261                         c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0x6ED9EBA1 + buff[37];
262                         e = (e << 30) | (e >> 2);
263
264                         b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0x6ED9EBA1 + buff[38];
265                         d = (d << 30) | (d >> 2);
266
267                         a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0x6ED9EBA1 + buff[39];
268                         c = (c << 30) | (c >> 2);
269
270                         // ---- Round 3 --------
271   
272                         e += ((a << 5) | (a >> 27)) + ((b&c) | (b&d) | (c&d)) + 0x8F1BBCDC + buff[40];
273                         b = (b << 30) | (b >> 2);
274
275                         d += ((e << 5) | (e >> 27)) + ((a&b) | (a&c) | (b&c)) + 0x8F1BBCDC + buff[41];
276                         a = (a << 30) | (a >> 2);
277
278                         c += ((d << 5) | (d >> 27)) + ((e&a) | (e&b) | (a&b)) + 0x8F1BBCDC + buff[42];
279                         e = (e << 30) | (e >> 2);
280
281                         b += ((c << 5) | (c >> 27)) + ((d&e) | (d&a) | (e&a)) + 0x8F1BBCDC + buff[43];
282                         d = (d << 30) | (d >> 2);
283
284                         a += ((b << 5) | (b >> 27)) + ((c&d) | (c&e) | (d&e)) + 0x8F1BBCDC + buff[44];
285                         c = (c << 30) | (c >> 2);
286
287                         e += ((a << 5) | (a >> 27)) + ((b&c) | (b&d) | (c&d)) + 0x8F1BBCDC + buff[45];
288                         b = (b << 30) | (b >> 2);
289
290                         d += ((e << 5) | (e >> 27)) + ((a&b) | (a&c) | (b&c)) + 0x8F1BBCDC + buff[46];
291                         a = (a << 30) | (a >> 2);
292
293                         c += ((d << 5) | (d >> 27)) + ((e&a) | (e&b) | (a&b)) + 0x8F1BBCDC + buff[47];
294                         e = (e << 30) | (e >> 2);
295
296                         b += ((c << 5) | (c >> 27)) + ((d&e) | (d&a) | (e&a)) + 0x8F1BBCDC + buff[48];
297                         d = (d << 30) | (d >> 2);
298
299                         a += ((b << 5) | (b >> 27)) + ((c&d) | (c&e) | (d&e)) + 0x8F1BBCDC + buff[49];
300                         c = (c << 30) | (c >> 2);
301
302                         e += ((a << 5) | (a >> 27)) + ((b&c) | (b&d) | (c&d)) + 0x8F1BBCDC + buff[50];
303                         b = (b << 30) | (b >> 2);
304
305                         d += ((e << 5) | (e >> 27)) + ((a&b) | (a&c) | (b&c)) + 0x8F1BBCDC + buff[51];
306                         a = (a << 30) | (a >> 2);
307
308                         c += ((d << 5) | (d >> 27)) + ((e&a) | (e&b) | (a&b)) + 0x8F1BBCDC + buff[52];
309                         e = (e << 30) | (e >> 2);
310
311                         b += ((c << 5) | (c >> 27)) + ((d&e) | (d&a) | (e&a)) + 0x8F1BBCDC + buff[53];
312                         d = (d << 30) | (d >> 2);
313
314                         a += ((b << 5) | (b >> 27)) + ((c&d) | (c&e) | (d&e)) + 0x8F1BBCDC + buff[54];
315                         c = (c << 30) | (c >> 2);
316
317                         e += ((a << 5) | (a >> 27)) + ((b&c) | (b&d) | (c&d)) + 0x8F1BBCDC + buff[55];
318                         b = (b << 30) | (b >> 2);
319
320                         d += ((e << 5) | (e >> 27)) + ((a&b) | (a&c) | (b&c)) + 0x8F1BBCDC + buff[56];
321                         a = (a << 30) | (a >> 2);
322
323                         c += ((d << 5) | (d >> 27)) + ((e&a) | (e&b) | (a&b)) + 0x8F1BBCDC + buff[57];
324                         e = (e << 30) | (e >> 2);
325
326                         b += ((c << 5) | (c >> 27)) + ((d&e) | (d&a) | (e&a)) + 0x8F1BBCDC + buff[58];
327                         d = (d << 30) | (d >> 2);
328
329                         a += ((b << 5) | (b >> 27)) + ((c&d) | (c&e) | (d&e)) + 0x8F1BBCDC + buff[59];
330                         c = (c << 30) | (c >> 2);
331
332                         // ---- Round 4 --------
333   
334                         e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0xCA62C1D6 + buff[60];
335                         b = (b << 30) | (b >> 2);
336
337                         d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0xCA62C1D6 + buff[61];
338                         a = (a << 30) | (a >> 2);
339
340                         c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0xCA62C1D6 + buff[62];
341                         e = (e << 30) | (e >> 2);
342
343                         b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0xCA62C1D6 + buff[63];
344                         d = (d << 30) | (d >> 2);
345
346                         a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0xCA62C1D6 + buff[64];
347                         c = (c << 30) | (c >> 2);
348
349                         e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0xCA62C1D6 + buff[65];
350                         b = (b << 30) | (b >> 2);
351
352                         d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0xCA62C1D6 + buff[66];
353                         a = (a << 30) | (a >> 2);
354
355                         c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0xCA62C1D6 + buff[67];
356                         e = (e << 30) | (e >> 2);
357
358                         b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0xCA62C1D6 + buff[68];
359                         d = (d << 30) | (d >> 2);
360
361                         a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0xCA62C1D6 + buff[69];
362                         c = (c << 30) | (c >> 2);
363
364                         e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0xCA62C1D6 + buff[70];
365                         b = (b << 30) | (b >> 2);
366
367                         d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0xCA62C1D6 + buff[71];
368                         a = (a << 30) | (a >> 2);
369
370                         c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0xCA62C1D6 + buff[72];
371                         e = (e << 30) | (e >> 2);
372
373                         b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0xCA62C1D6 + buff[73];
374                         d = (d << 30) | (d >> 2);
375
376                         a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0xCA62C1D6 + buff[74];
377                         c = (c << 30) | (c >> 2);
378
379                         e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0xCA62C1D6 + buff[75];
380                         b = (b << 30) | (b >> 2);
381
382                         d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0xCA62C1D6 + buff[76];
383                         a = (a << 30) | (a >> 2);
384
385                         c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0xCA62C1D6 + buff[77];
386                         e = (e << 30) | (e >> 2);
387
388                         b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0xCA62C1D6 + buff[78];
389                         d = (d << 30) | (d >> 2);
390
391                         a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0xCA62C1D6 + buff[79];
392                         c = (c << 30) | (c >> 2);
393
394
395                         _H[0] += a;
396                         _H[1] += b;
397                         _H[2] += c;
398                         _H[3] += d;
399                         _H[4] += e;
400                 }
401         
402                 private void ProcessFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount) 
403                 {
404                         ulong total = count + (ulong)inputCount;
405                         int paddingSize = (56 - (int)(total % BLOCK_SIZE_BYTES));
406
407                         if (paddingSize < 1)
408                                 paddingSize += BLOCK_SIZE_BYTES;
409
410                         byte[] fooBuffer = new byte[inputCount+paddingSize+8];
411
412                         for (int i=0; i<inputCount; i++) {
413                                 fooBuffer[i] = inputBuffer[i+inputOffset];
414                         }
415
416                         fooBuffer[inputCount] = 0x80;
417                         for (int i=inputCount+1; i<inputCount+paddingSize; i++) {
418                                 fooBuffer[i] = 0x00;
419                         }
420
421                         // I deal in bytes. The algorithm deals in bits.
422                         ulong size = total << 3;
423                         AddLength (size, fooBuffer, inputCount+paddingSize);
424                         ProcessBlock (fooBuffer, 0);
425
426                         if (inputCount+paddingSize+8 == 128) {
427                                 ProcessBlock(fooBuffer, 64);
428                         }
429                 }
430
431                 internal void AddLength (ulong length, byte[] buffer, int position)
432                 {
433                         buffer [position++] = (byte)(length >> 56);
434                         buffer [position++] = (byte)(length >> 48);
435                         buffer [position++] = (byte)(length >> 40);
436                         buffer [position++] = (byte)(length >> 32);
437                         buffer [position++] = (byte)(length >> 24);
438                         buffer [position++] = (byte)(length >> 16);
439                         buffer [position++] = (byte)(length >>  8);
440                         buffer [position]   = (byte)(length);
441                 }
442         }
443
444 #if NET_2_0
445         [ComVisible (true)]
446 #endif
447         public sealed class SHA1CryptoServiceProvider : SHA1 {
448
449                 private SHA1Internal sha;
450
451                 public SHA1CryptoServiceProvider () 
452                 {
453                         sha = new SHA1Internal ();
454                 }
455
456                 ~SHA1CryptoServiceProvider () 
457                 {
458                         Dispose (false);
459                 }
460
461                 protected override void Dispose (bool disposing) 
462                 {
463                         // nothing new to do (managed implementation)
464                         base.Dispose (disposing);
465                 }
466
467                 protected override void HashCore (byte[] rgb, int start, int size) 
468                 {
469                         State = 1;
470                         sha.HashCore (rgb, start, size);
471                 }
472
473                 protected override byte[] HashFinal () 
474                 {
475                         State = 0;
476                         return sha.HashFinal ();
477                 }
478
479                 public override void Initialize () 
480                 {
481                         sha.Initialize ();
482                 }
483         }
484 }