2004-05-06 Sebastien Pouliot <sebastien@ximian.com>
[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 // (C) 2004 Novell (http://www.novell.com)
10 //
11
12 // Note:
13 // The MS Framework includes two (almost) identical class for SHA1.
14 //      SHA1Managed is a 100% managed implementation.
15 //      SHA1CryptoServiceProvider (this file) is a wrapper on CryptoAPI.
16 // Mono must provide those two class for binary compatibility.
17 // In our case both class are wrappers around a managed internal class SHA1Internal.
18
19 namespace System.Security.Cryptography {
20
21         internal class SHA1Internal {
22         
23                 private const int BLOCK_SIZE_BYTES =  64;
24                 private const int HASH_SIZE_BYTES  =  20;
25                 private uint[] _H;  // these are my chaining variables
26                 private uint count;
27                 private byte[] _ProcessingBuffer;   // Used to start data when passed less than a block worth.
28                 private int _ProcessingBufferCount; // Counts how much data we have stored that still needs processed.
29
30                 public SHA1Internal () 
31                 {
32                         _H = new uint[5];
33                         _ProcessingBuffer = new byte[BLOCK_SIZE_BYTES];
34                         
35                         Initialize();
36                 }
37
38                 public void HashCore (byte[] rgb, int start, int size) 
39                 {
40                         int i;
41
42                         if (_ProcessingBufferCount != 0) {
43                                 if (size < (BLOCK_SIZE_BYTES - _ProcessingBufferCount)) {
44                                         System.Buffer.BlockCopy (rgb, start, _ProcessingBuffer, _ProcessingBufferCount, size);
45                                         _ProcessingBufferCount += size;
46                                         return;
47                                 }
48                                 else {
49                                         i = (BLOCK_SIZE_BYTES - _ProcessingBufferCount);
50                                         System.Buffer.BlockCopy (rgb, start, _ProcessingBuffer, _ProcessingBufferCount, i);
51                                         ProcessBlock (_ProcessingBuffer, 0);
52                                         _ProcessingBufferCount = 0;
53                                         start += i;
54                                         size -= i;
55                                 }
56                         }
57
58                         for (i=0; i<size-size%BLOCK_SIZE_BYTES; i += BLOCK_SIZE_BYTES) {
59                                 ProcessBlock (rgb, start+i);
60                         }
61
62                         if (size%BLOCK_SIZE_BYTES != 0) {
63                                 System.Buffer.BlockCopy (rgb, size-size%BLOCK_SIZE_BYTES+start, _ProcessingBuffer, 0, size%BLOCK_SIZE_BYTES);
64                                 _ProcessingBufferCount = size%BLOCK_SIZE_BYTES;
65                         }
66                 }
67         
68                 public byte[] HashFinal () 
69                 {
70                         byte[] hash = new byte[20];
71
72                         ProcessFinalBlock (_ProcessingBuffer, 0, _ProcessingBufferCount);
73
74                         for (int i=0; i<5; i++) {
75                                 for (int j=0; j<4; j++) {
76                                         hash [i*4+j] = (byte)(_H[i] >> (8*(3-j)));
77                                 }
78                         }
79
80                         return hash;
81                 }
82
83                 public void Initialize () 
84                 {
85                         count = 0;
86                         _ProcessingBufferCount = 0;
87
88                         _H[0] = 0x67452301;
89                         _H[1] = 0xefcdab89;
90                         _H[2] = 0x98badcfe;
91                         _H[3] = 0x10325476;
92                         _H[4] = 0xC3D2E1F0;
93                 }
94
95                 private void ProcessBlock(byte[] inputBuffer, int inputOffset) 
96                 {
97                         uint[] buff = new uint[80];
98                         uint a, b, c, d, e;
99                         int i;
100
101                         count += BLOCK_SIZE_BYTES;
102                 
103                         for (i=0; i<16; i++) {
104                                 buff[i] = ((uint)(inputBuffer[inputOffset+4*i]) << 24)
105                                         | ((uint)(inputBuffer[inputOffset+4*i+1]) << 16)
106                                         | ((uint)(inputBuffer[inputOffset+4*i+2]) <<  8)
107                                         | ((uint)(inputBuffer[inputOffset+4*i+3]));
108                         }
109
110                         for (i=16; i<80; i++) {
111                                 buff[i] = ((buff[i-3] ^ buff[i-8] ^ buff[i-14] ^ buff[i-16]) << 1)
112                                         | ((buff[i-3] ^ buff[i-8] ^ buff[i-14] ^ buff[i-16]) >> 31);
113                         }
114                 
115                         a = _H[0];
116                         b = _H[1];
117                         c = _H[2];
118                         d = _H[3];
119                         e = _H[4];
120
121                         // This function was unrolled because it seems to be doubling our performance with current compiler/VM.
122                         // Possibly roll up if this changes.
123         
124                         // ---- Round 1 --------
125   
126                         e += ((a << 5) | (a >> 27)) + (((c ^ d) & b) ^ d) + 0x5A827999 + buff[0];
127                         b = (b << 30) | (b >> 2);
128
129                         d += ((e << 5) | (e >> 27)) + (((b ^ c) & a) ^ c) + 0x5A827999 + buff[1];
130                         a = (a << 30) | (a >> 2);
131
132                         c += ((d << 5) | (d >> 27)) + (((a ^ b) & e) ^ b) + 0x5A827999 + buff[2];
133                         e = (e << 30) | (e >> 2);
134
135                         b += ((c << 5) | (c >> 27)) + (((e ^ a) & d) ^ a) + 0x5A827999 + buff[3];
136                         d = (d << 30) | (d >> 2);
137
138                         a += ((b << 5) | (b >> 27)) + (((d ^ e) & c) ^ e) + 0x5A827999 + buff[4];
139                         c = (c << 30) | (c >> 2);
140
141                         e += ((a << 5) | (a >> 27)) + (((c ^ d) & b) ^ d) + 0x5A827999 + buff[5];
142                         b = (b << 30) | (b >> 2);
143
144                         d += ((e << 5) | (e >> 27)) + (((b ^ c) & a) ^ c) + 0x5A827999 + buff[6];
145                         a = (a << 30) | (a >> 2);
146
147                         c += ((d << 5) | (d >> 27)) + (((a ^ b) & e) ^ b) + 0x5A827999 + buff[7];
148                         e = (e << 30) | (e >> 2);
149
150                         b += ((c << 5) | (c >> 27)) + (((e ^ a) & d) ^ a) + 0x5A827999 + buff[8];
151                         d = (d << 30) | (d >> 2);
152
153                         a += ((b << 5) | (b >> 27)) + (((d ^ e) & c) ^ e) + 0x5A827999 + buff[9];
154                         c = (c << 30) | (c >> 2);
155
156                         e += ((a << 5) | (a >> 27)) + (((c ^ d) & b) ^ d) + 0x5A827999 + buff[10];
157                         b = (b << 30) | (b >> 2);
158
159                         d += ((e << 5) | (e >> 27)) + (((b ^ c) & a) ^ c) + 0x5A827999 + buff[11];
160                         a = (a << 30) | (a >> 2);
161
162                         c += ((d << 5) | (d >> 27)) + (((a ^ b) & e) ^ b) + 0x5A827999 + buff[12];
163                         e = (e << 30) | (e >> 2);
164
165                         b += ((c << 5) | (c >> 27)) + (((e ^ a) & d) ^ a) + 0x5A827999 + buff[13];
166                         d = (d << 30) | (d >> 2);
167
168                         a += ((b << 5) | (b >> 27)) + (((d ^ e) & c) ^ e) + 0x5A827999 + buff[14];
169                         c = (c << 30) | (c >> 2);
170
171                         e += ((a << 5) | (a >> 27)) + (((c ^ d) & b) ^ d) + 0x5A827999 + buff[15];
172                         b = (b << 30) | (b >> 2);
173
174                         d += ((e << 5) | (e >> 27)) + (((b ^ c) & a) ^ c) + 0x5A827999 + buff[16];
175                         a = (a << 30) | (a >> 2);
176
177                         c += ((d << 5) | (d >> 27)) + (((a ^ b) & e) ^ b) + 0x5A827999 + buff[17];
178                         e = (e << 30) | (e >> 2);
179
180                         b += ((c << 5) | (c >> 27)) + (((e ^ a) & d) ^ a) + 0x5A827999 + buff[18];
181                         d = (d << 30) | (d >> 2);
182
183                         a += ((b << 5) | (b >> 27)) + (((d ^ e) & c) ^ e) + 0x5A827999 + buff[19];
184                         c = (c << 30) | (c >> 2);
185
186                         // ---- Round 2 --------
187   
188                         e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0x6ED9EBA1 + buff[20];
189                         b = (b << 30) | (b >> 2);
190
191                         d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0x6ED9EBA1 + buff[21];
192                         a = (a << 30) | (a >> 2);
193
194                         c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0x6ED9EBA1 + buff[22];
195                         e = (e << 30) | (e >> 2);
196
197                         b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0x6ED9EBA1 + buff[23];
198                         d = (d << 30) | (d >> 2);
199
200                         a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0x6ED9EBA1 + buff[24];
201                         c = (c << 30) | (c >> 2);
202
203                         e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0x6ED9EBA1 + buff[25];
204                         b = (b << 30) | (b >> 2);
205
206                         d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0x6ED9EBA1 + buff[26];
207                         a = (a << 30) | (a >> 2);
208
209                         c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0x6ED9EBA1 + buff[27];
210                         e = (e << 30) | (e >> 2);
211
212                         b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0x6ED9EBA1 + buff[28];
213                         d = (d << 30) | (d >> 2);
214
215                         a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0x6ED9EBA1 + buff[29];
216                         c = (c << 30) | (c >> 2);
217
218                         e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0x6ED9EBA1 + buff[30];
219                         b = (b << 30) | (b >> 2);
220
221                         d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0x6ED9EBA1 + buff[31];
222                         a = (a << 30) | (a >> 2);
223
224                         c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0x6ED9EBA1 + buff[32];
225                         e = (e << 30) | (e >> 2);
226
227                         b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0x6ED9EBA1 + buff[33];
228                         d = (d << 30) | (d >> 2);
229
230                         a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0x6ED9EBA1 + buff[34];
231                         c = (c << 30) | (c >> 2);
232
233                         e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0x6ED9EBA1 + buff[35];
234                         b = (b << 30) | (b >> 2);
235
236                         d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0x6ED9EBA1 + buff[36];
237                         a = (a << 30) | (a >> 2);
238
239                         c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0x6ED9EBA1 + buff[37];
240                         e = (e << 30) | (e >> 2);
241
242                         b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0x6ED9EBA1 + buff[38];
243                         d = (d << 30) | (d >> 2);
244
245                         a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0x6ED9EBA1 + buff[39];
246                         c = (c << 30) | (c >> 2);
247
248                         // ---- Round 3 --------
249   
250                         e += ((a << 5) | (a >> 27)) + ((b&c) | (b&d) | (c&d)) + 0x8F1BBCDC + buff[40];
251                         b = (b << 30) | (b >> 2);
252
253                         d += ((e << 5) | (e >> 27)) + ((a&b) | (a&c) | (b&c)) + 0x8F1BBCDC + buff[41];
254                         a = (a << 30) | (a >> 2);
255
256                         c += ((d << 5) | (d >> 27)) + ((e&a) | (e&b) | (a&b)) + 0x8F1BBCDC + buff[42];
257                         e = (e << 30) | (e >> 2);
258
259                         b += ((c << 5) | (c >> 27)) + ((d&e) | (d&a) | (e&a)) + 0x8F1BBCDC + buff[43];
260                         d = (d << 30) | (d >> 2);
261
262                         a += ((b << 5) | (b >> 27)) + ((c&d) | (c&e) | (d&e)) + 0x8F1BBCDC + buff[44];
263                         c = (c << 30) | (c >> 2);
264
265                         e += ((a << 5) | (a >> 27)) + ((b&c) | (b&d) | (c&d)) + 0x8F1BBCDC + buff[45];
266                         b = (b << 30) | (b >> 2);
267
268                         d += ((e << 5) | (e >> 27)) + ((a&b) | (a&c) | (b&c)) + 0x8F1BBCDC + buff[46];
269                         a = (a << 30) | (a >> 2);
270
271                         c += ((d << 5) | (d >> 27)) + ((e&a) | (e&b) | (a&b)) + 0x8F1BBCDC + buff[47];
272                         e = (e << 30) | (e >> 2);
273
274                         b += ((c << 5) | (c >> 27)) + ((d&e) | (d&a) | (e&a)) + 0x8F1BBCDC + buff[48];
275                         d = (d << 30) | (d >> 2);
276
277                         a += ((b << 5) | (b >> 27)) + ((c&d) | (c&e) | (d&e)) + 0x8F1BBCDC + buff[49];
278                         c = (c << 30) | (c >> 2);
279
280                         e += ((a << 5) | (a >> 27)) + ((b&c) | (b&d) | (c&d)) + 0x8F1BBCDC + buff[50];
281                         b = (b << 30) | (b >> 2);
282
283                         d += ((e << 5) | (e >> 27)) + ((a&b) | (a&c) | (b&c)) + 0x8F1BBCDC + buff[51];
284                         a = (a << 30) | (a >> 2);
285
286                         c += ((d << 5) | (d >> 27)) + ((e&a) | (e&b) | (a&b)) + 0x8F1BBCDC + buff[52];
287                         e = (e << 30) | (e >> 2);
288
289                         b += ((c << 5) | (c >> 27)) + ((d&e) | (d&a) | (e&a)) + 0x8F1BBCDC + buff[53];
290                         d = (d << 30) | (d >> 2);
291
292                         a += ((b << 5) | (b >> 27)) + ((c&d) | (c&e) | (d&e)) + 0x8F1BBCDC + buff[54];
293                         c = (c << 30) | (c >> 2);
294
295                         e += ((a << 5) | (a >> 27)) + ((b&c) | (b&d) | (c&d)) + 0x8F1BBCDC + buff[55];
296                         b = (b << 30) | (b >> 2);
297
298                         d += ((e << 5) | (e >> 27)) + ((a&b) | (a&c) | (b&c)) + 0x8F1BBCDC + buff[56];
299                         a = (a << 30) | (a >> 2);
300
301                         c += ((d << 5) | (d >> 27)) + ((e&a) | (e&b) | (a&b)) + 0x8F1BBCDC + buff[57];
302                         e = (e << 30) | (e >> 2);
303
304                         b += ((c << 5) | (c >> 27)) + ((d&e) | (d&a) | (e&a)) + 0x8F1BBCDC + buff[58];
305                         d = (d << 30) | (d >> 2);
306
307                         a += ((b << 5) | (b >> 27)) + ((c&d) | (c&e) | (d&e)) + 0x8F1BBCDC + buff[59];
308                         c = (c << 30) | (c >> 2);
309
310                         // ---- Round 4 --------
311   
312                         e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0xCA62C1D6 + buff[60];
313                         b = (b << 30) | (b >> 2);
314
315                         d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0xCA62C1D6 + buff[61];
316                         a = (a << 30) | (a >> 2);
317
318                         c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0xCA62C1D6 + buff[62];
319                         e = (e << 30) | (e >> 2);
320
321                         b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0xCA62C1D6 + buff[63];
322                         d = (d << 30) | (d >> 2);
323
324                         a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0xCA62C1D6 + buff[64];
325                         c = (c << 30) | (c >> 2);
326
327                         e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0xCA62C1D6 + buff[65];
328                         b = (b << 30) | (b >> 2);
329
330                         d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0xCA62C1D6 + buff[66];
331                         a = (a << 30) | (a >> 2);
332
333                         c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0xCA62C1D6 + buff[67];
334                         e = (e << 30) | (e >> 2);
335
336                         b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0xCA62C1D6 + buff[68];
337                         d = (d << 30) | (d >> 2);
338
339                         a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0xCA62C1D6 + buff[69];
340                         c = (c << 30) | (c >> 2);
341
342                         e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0xCA62C1D6 + buff[70];
343                         b = (b << 30) | (b >> 2);
344
345                         d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0xCA62C1D6 + buff[71];
346                         a = (a << 30) | (a >> 2);
347
348                         c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0xCA62C1D6 + buff[72];
349                         e = (e << 30) | (e >> 2);
350
351                         b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0xCA62C1D6 + buff[73];
352                         d = (d << 30) | (d >> 2);
353
354                         a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0xCA62C1D6 + buff[74];
355                         c = (c << 30) | (c >> 2);
356
357                         e += ((a << 5) | (a >> 27)) + (b ^ c ^ d) + 0xCA62C1D6 + buff[75];
358                         b = (b << 30) | (b >> 2);
359
360                         d += ((e << 5) | (e >> 27)) + (a ^ b ^ c) + 0xCA62C1D6 + buff[76];
361                         a = (a << 30) | (a >> 2);
362
363                         c += ((d << 5) | (d >> 27)) + (e ^ a ^ b) + 0xCA62C1D6 + buff[77];
364                         e = (e << 30) | (e >> 2);
365
366                         b += ((c << 5) | (c >> 27)) + (d ^ e ^ a) + 0xCA62C1D6 + buff[78];
367                         d = (d << 30) | (d >> 2);
368
369                         a += ((b << 5) | (b >> 27)) + (c ^ d ^ e) + 0xCA62C1D6 + buff[79];
370                         c = (c << 30) | (c >> 2);
371
372
373                         _H[0] += a;
374                         _H[1] += b;
375                         _H[2] += c;
376                         _H[3] += d;
377                         _H[4] += e;
378                 }
379         
380                 private void ProcessFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount) 
381                 {
382                         int i;
383                         int paddingSize = (int)(56 - (inputCount + count) % BLOCK_SIZE_BYTES);
384
385                         if (paddingSize < 1)
386                                 paddingSize += BLOCK_SIZE_BYTES;
387
388                         byte[] fooBuffer = new byte[inputCount+paddingSize+8];
389
390                         for (i=0; i<inputCount; i++) {
391                                 fooBuffer[i] = inputBuffer[i+inputOffset];
392                         }
393
394                         fooBuffer[inputCount] = 0x80;
395                         for (i=inputCount+1; i<inputCount+paddingSize; i++) {
396                                 fooBuffer[i] = 0x00;
397                         }
398
399                         // I deal in bytes. The algorithm deals in bits.
400                         uint size = (uint)((count+inputCount) << 3);
401
402                         fooBuffer[inputCount+paddingSize]   = 0x00;
403                         fooBuffer[inputCount+paddingSize+1] = 0x00;
404                         fooBuffer[inputCount+paddingSize+2] = 0x00;
405                         fooBuffer[inputCount+paddingSize+3] = 0x00;
406
407                         fooBuffer[inputCount+paddingSize+4] = (byte)((size) >> 24);
408                         fooBuffer[inputCount+paddingSize+5] = (byte)((size) >> 16);
409                         fooBuffer[inputCount+paddingSize+6] = (byte)((size) >>  8);
410                         fooBuffer[inputCount+paddingSize+7] = (byte)((size) >>  0);
411
412                         ProcessBlock(fooBuffer, 0);
413
414                         if (inputCount+paddingSize+8 == 128) {
415                                 ProcessBlock(fooBuffer, 64);
416                         }
417                 }
418         }
419
420         public sealed class SHA1CryptoServiceProvider : SHA1 {
421
422                 private SHA1Internal sha;
423
424                 public SHA1CryptoServiceProvider () 
425                 {
426                         sha = new SHA1Internal ();
427                 }
428
429                 ~SHA1CryptoServiceProvider () 
430                 {
431                         Dispose (false);
432                 }
433
434                 protected override void Dispose (bool disposing) 
435                 {
436                         // nothing new to do (managed implementation)
437                         base.Dispose (disposing);
438                 }
439
440                 protected override void HashCore (byte[] rgb, int start, int size) 
441                 {
442                         State = 1;
443                         sha.HashCore (rgb, start, size);
444                 }
445
446                 protected override byte[] HashFinal () 
447                 {
448                         State = 0;
449                         return sha.HashFinal ();
450                 }
451
452                 public override void Initialize () 
453                 {
454                         sha.Initialize ();
455                 }
456         }
457 }